diff --git a/src/common/aka_array.cc b/src/common/aka_array.cc index 31bf3f4fb..08e70d815 100644 --- a/src/common/aka_array.cc +++ b/src/common/aka_array.cc @@ -1,123 +1,123 @@ /** * @file aka_array.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Aug 18 2015 * * @brief Implementation of akantu::Array * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <memory> #include <utility> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_array.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* Functions ArrayBase */ /* -------------------------------------------------------------------------- */ ArrayBase::ArrayBase(ID id) : id(std::move(id)), allocated_size(0), size(0), nb_component(1), size_of_type(0) {} /* -------------------------------------------------------------------------- */ ArrayBase::~ArrayBase() = default; /* -------------------------------------------------------------------------- */ void ArrayBase::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "ArrayBase [" << std::endl; stream << space << " + size : " << size << std::endl; stream << space << " + nb component : " << nb_component << std::endl; stream << space << " + allocated size : " << allocated_size << std::endl; Real mem_size = (allocated_size * nb_component * size_of_type) / 1024.; stream << space << " + size of type : " << size_of_type << "B" << std::endl; stream << space << " + memory allocated : " << mem_size << "kB" << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ template <> Int Array<Real>::find(const Real & elem) const { AKANTU_DEBUG_IN(); UInt i = 0; Real epsilon = std::numeric_limits<Real>::epsilon(); for (; (i < size) && (fabs(values[i] - elem) <= epsilon); ++i) ; AKANTU_DEBUG_OUT(); return (i == size) ? -1 : (Int)i; } /* -------------------------------------------------------------------------- */ template <> Array<ElementType> & Array<ElementType>::operator*=(__attribute__((unused)) const ElementType & alpha) { AKANTU_DEBUG_TO_IMPLEMENT(); return *this; } template <> Array<ElementType> & Array<ElementType>:: operator-=(__attribute__((unused)) const Array<ElementType> & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); return *this; } template <> Array<ElementType> & Array<ElementType>:: operator+=(__attribute__((unused)) const Array<ElementType> & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); return *this; } template <> Array<char> & Array<char>::operator*=(__attribute__((unused)) const char & alpha) { AKANTU_DEBUG_TO_IMPLEMENT(); return *this; } template <> Array<char> & Array<char>::operator-=(__attribute__((unused)) const Array<char> & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); return *this; } template <> Array<char> & Array<char>::operator+=(__attribute__((unused)) const Array<char> & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); return *this; } -__END_AKANTU__ +} // akantu diff --git a/src/common/aka_blas_lapack.hh b/src/common/aka_blas_lapack.hh index 951944ec0..725fbcd0e 100644 --- a/src/common/aka_blas_lapack.hh +++ b/src/common/aka_blas_lapack.hh @@ -1,343 +1,343 @@ /** * @file aka_blas_lapack.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Mar 06 2013 * @date last modification: Mon Jan 18 2016 * * @brief Interface of the Fortran BLAS/LAPACK libraries * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_BLAS_LAPACK_HH__ #define __AKANTU_AKA_BLAS_LAPACK_HH__ /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_BLAS #include "aka_fortran_mangling.hh" extern "C" { /* ------------------------------------------------------------------------ */ /* Double precision */ /* ------------------------------------------------------------------------ */ // LEVEL 1 double AKA_FC_GLOBAL(ddot, DDOT)(int *, double *, int *, double *, int *); void AKA_FC_GLOBAL(daxpy, DAXPY)(int *, double *, double *, int *, double *, int *); // LEVEL 2 void AKA_FC_GLOBAL(dgemv, DGEMV)(char *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); // LEVEL 3 void AKA_FC_GLOBAL(dgemm, DGEMM)(char *, char *, int *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); /* ------------------------------------------------------------------------ */ /* Simple precision */ /* ------------------------------------------------------------------------ */ // LEVEL 1 float AKA_FC_GLOBAL(sdot, SDOT)(int *, float *, int *, float *, int *); void AKA_FC_GLOBAL(saxpy, SAXPY)(int *, float *, float *, int *, float *, int *); // LEVEL 2 void AKA_FC_GLOBAL(sgemv, SGEMV)(char *, int *, int *, float *, float *, int *, float *, int *, float *, float *, int *); // LEVEL 3 void AKA_FC_GLOBAL(sgemm, SGEMM)(char *, char *, int *, int *, int *, float *, float *, int *, float *, int *, float *, float *, int *); } #endif -__BEGIN_AKANTU__ +namespace akantu { #define AKANTU_WARNING_IGNORE_UNUSED_PARAMETER #include "aka_warning.hh" /// Wrapper around the S/DDOT BLAS function that returns the dot product of two /// vectors template <typename T> inline T aka_dot(int * n, T * x, int * incx, T * y, int * incy) { AKANTU_DEBUG_ERROR(debug::demangle(typeid(T).name()) << "is not a type recognized, or you didn't activated " "BLAS in the compilation options!"); } /// Wrapper around the S/DAXPY BLAS function that computes \f$y := \alpha x + /// y\f$ template <typename T> inline void aka_axpy(int * n, T * alpha, T * x, int * incx, T * y, int * incy) { AKANTU_DEBUG_ERROR(debug::demangle(typeid(T).name()) << "is not a type recognized, or you didn't activated " "BLAS in the compilation options!"); } /// Wrapper around the S/DGEMV BLAS function that computes matrix-vector product /// \f$y := \alpha A^{(T)}x + \beta y \f$ template <typename T> inline void aka_gemv(char * trans, int * m, int * n, T * alpha, T * a, int * lda, T * x, int * incx, T * beta, T * y, int * incy) { AKANTU_DEBUG_ERROR(debug::demangle(typeid(T).name()) << "is not a type recognized, or you didn't activated " "BLAS in the compilation options!"); } /// Wrapper around the S/DGEMM BLAS function that computes the product of two /// matrices \f$C := \alpha A^{(T)} B^{(T)} + \beta C \f$ template <typename T> inline void aka_gemm(char * transa, char * transb, int * m, int * n, int * k, T * alpha, T * a, int * lda, T * b, int * ldb, T * beta, T * c, int * ldc) { AKANTU_DEBUG_ERROR(debug::demangle(typeid(T).name()) << "is not a type recognized, or you didn't activated " "BLAS in the compilation options!"); } #if defined(AKANTU_USE_BLAS) template <> inline double aka_dot<double>(int * n, double * x, int * incx, double * y, int * incy) { return AKA_FC_GLOBAL(ddot, DDOT)(n, x, incx, y, incy); } template <> inline void aka_axpy(int * n, double * alpha, double * x, int * incx, double * y, int * incy) { return AKA_FC_GLOBAL(daxpy, DAXPY)(n, alpha, x, incx, y, incy); } template <> inline void aka_gemv<double>(char * trans, int * m, int * n, double * alpha, double * a, int * lda, double * x, int * incx, double * beta, double * y, int * incy) { return AKA_FC_GLOBAL(dgemv, DGEMV)(trans, m, n, alpha, a, lda, x, incx, beta, y, incy); } template <> inline void aka_gemm<double>(char * transa, char * transb, int * m, int * n, int * k, double * alpha, double * a, int * lda, double * b, int * ldb, double * beta, double * c, int * ldc) { AKA_FC_GLOBAL(dgemm, DGEMM) (transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template <> inline float aka_dot<float>(int * n, float * x, int * incx, float * y, int * incy) { return AKA_FC_GLOBAL(sdot, SDOT)(n, x, incx, y, incy); } template <> inline void aka_axpy(int * n, float * alpha, float * x, int * incx, float * y, int * incy) { return AKA_FC_GLOBAL(daxpy, DAXPY)(n, alpha, x, incx, y, incy); } template <> inline void aka_gemv<float>(char * trans, int * m, int * n, float * alpha, float * a, int * lda, float * x, int * incx, float * beta, float * y, int * incy) { AKA_FC_GLOBAL(sgemv, SGEMV) (trans, m, n, alpha, a, lda, x, incx, beta, y, incy); } template <> inline void aka_gemm<float>(char * transa, char * transb, int * m, int * n, int * k, float * alpha, float * a, int * lda, float * b, int * ldb, float * beta, float * c, int * ldc) { AKA_FC_GLOBAL(sgemm, SGEMM) (transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc); } #endif -__END_AKANTU__ +} // akantu #ifdef AKANTU_USE_LAPACK #include "aka_fortran_mangling.hh" extern "C" { /* ------------------------------------------------------------------------ */ /* Double general matrix */ /* ------------------------------------------------------------------------ */ /// compute the eigenvalues/vectors void AKA_FC_GLOBAL(dgeev, DGEEV)(char * jobvl, char * jobvr, int * n, double * a, int * lda, double * wr, double * wi, double * vl, int * ldvl, double * vr, int * ldvr, double * work, int * lwork, int * info); /// LU decomposition of a general matrix void AKA_FC_GLOBAL(dgetrf, DGETRF)(int * m, int * n, double * a, int * lda, int * ipiv, int * info); /// generate inverse of a matrix given its LU decomposition void AKA_FC_GLOBAL(dgetri, DGETRI)(int * n, double * a, int * lda, int * ipiv, double * work, int * lwork, int * info); /// solving A x = b using a LU factorization void AKA_FC_GLOBAL(dgetrs, DGETRS)(char * trans, int * n, int * nrhs, double * A, int * lda, int * ipiv, double * b, int * ldb, int * info); /* ------------------------------------------------------------------------ */ /* Simple general matrix */ /* ------------------------------------------------------------------------ */ /// compute the eigenvalues/vectors void AKA_FC_GLOBAL(sgeev, SGEEV)(char * jobvl, char * jobvr, int * n, float * a, int * lda, float * wr, float * wi, float * vl, int * ldvl, float * vr, int * ldvr, float * work, int * lwork, int * info); /// LU decomposition of a general matrix void AKA_FC_GLOBAL(sgetrf, SGETRF)(int * m, int * n, float * a, int * lda, int * ipiv, int * info); /// generate inverse of a matrix given its LU decomposition void AKA_FC_GLOBAL(sgetri, SGETRI)(int * n, float * a, int * lda, int * ipiv, float * work, int * lwork, int * info); /// solving A x = b using a LU factorization void AKA_FC_GLOBAL(sgetrs, SGETRS)(char * trans, int * n, int * nrhs, float * A, int * lda, int * ipiv, float * b, int * ldb, int * info); } #endif // AKANTU_USE_LAPACK -__BEGIN_AKANTU__ +namespace akantu { /// Wrapper around the S/DGEEV BLAS function that computes the eigenvalues and /// eigenvectors of a matrix template <typename T> inline void aka_geev(char * jobvl, char * jobvr, int * n, T * a, int * lda, T * wr, T * wi, T * vl, int * ldvl, T * vr, int * ldvr, T * work, int * lwork, int * info) { AKANTU_DEBUG_ERROR(debug::demangle(typeid(T).name()) << "is not a type recognized, or you didn't activated " "LAPACK in the compilation options!"); } /// Wrapper around the S/DGETRF BLAS function that computes the LU decomposition /// of a matrix template <typename T> inline void aka_getrf(int * m, int * n, T * a, int * lda, int * ipiv, int * info) { AKANTU_DEBUG_ERROR(debug::demangle(typeid(T).name()) << "is not a type recognized, or you didn't activated " "LAPACK in the compilation options!"); } /// Wrapper around the S/DGETRI BLAS function that computes the inverse of a /// matrix given its LU decomposition template <typename T> inline void aka_getri(int * n, T * a, int * lda, int * ipiv, T * work, int * lwork, int * info) { AKANTU_DEBUG_ERROR(debug::demangle(typeid(T).name()) << "is not a type recognized, or you didn't activated " "LAPACK in the compilation options!"); } /// Wrapper around the S/DGETRS BLAS function that solves \f$A^{(T)}x = b\f$ /// using LU decomposition template <typename T> inline void aka_getrs(char * trans, int * n, int * nrhs, T * A, int * lda, int * ipiv, T * b, int * ldb, int * info) { AKANTU_DEBUG_ERROR(debug::demangle(typeid(T).name()) << "is not a type recognized, or you didn't activated " "LAPACK in the compilation options!"); } #include "aka_warning_restore.hh" #ifdef AKANTU_USE_LAPACK template <> inline void aka_geev<double>(char * jobvl, char * jobvr, int * n, double * a, int * lda, double * wr, double * wi, double * vl, int * ldvl, double * vr, int * ldvr, double * work, int * lwork, int * info) { AKA_FC_GLOBAL(dgeev, DGEEV) (jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork, info); } template <> inline void aka_getrf<double>(int * m, int * n, double * a, int * lda, int * ipiv, int * info) { AKA_FC_GLOBAL(dgetrf, DGETRF)(m, n, a, lda, ipiv, info); } template <> inline void aka_getri<double>(int * n, double * a, int * lda, int * ipiv, double * work, int * lwork, int * info) { AKA_FC_GLOBAL(dgetri, DGETRI)(n, a, lda, ipiv, work, lwork, info); } template <> inline void aka_getrs<double>(char * trans, int * n, int * nrhs, double * A, int * lda, int * ipiv, double * b, int * ldb, int * info) { AKA_FC_GLOBAL(dgetrs, DGETRS)(trans, n, nrhs, A, lda, ipiv, b, ldb, info); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template <> inline void aka_geev<float>(char * jobvl, char * jobvr, int * n, float * a, int * lda, float * wr, float * wi, float * vl, int * ldvl, float * vr, int * ldvr, float * work, int * lwork, int * info) { AKA_FC_GLOBAL(sgeev, SGEEV) (jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork, info); } template <> inline void aka_getrf<float>(int * m, int * n, float * a, int * lda, int * ipiv, int * info) { AKA_FC_GLOBAL(sgetrf, SGETRF)(m, n, a, lda, ipiv, info); } template <> inline void aka_getri<float>(int * n, float * a, int * lda, int * ipiv, float * work, int * lwork, int * info) { AKA_FC_GLOBAL(sgetri, SGETRI)(n, a, lda, ipiv, work, lwork, info); } template <> inline void aka_getrs<float>(char * trans, int * n, int * nrhs, float * A, int * lda, int * ipiv, float * b, int * ldb, int * info) { AKA_FC_GLOBAL(sgetrs, SGETRS)(trans, n, nrhs, A, lda, ipiv, b, ldb, info); } #endif -__END_AKANTU__ +} // akantu #endif /* __AKANTU_AKA_BLAS_LAPACK_HH__ */ diff --git a/src/common/aka_circular_array.hh b/src/common/aka_circular_array.hh index af005df7c..34ed0fb1b 100644 --- a/src/common/aka_circular_array.hh +++ b/src/common/aka_circular_array.hh @@ -1,140 +1,140 @@ /** * @file aka_circular_array.hh * * @author David Simon Kammer <david.kammer@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief class of circular array * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_CIRCULAR_ARRAY_HH__ #define __AKANTU_AKA_CIRCULAR_ARRAY_HH__ /* -------------------------------------------------------------------------- */ #include <typeinfo> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_array.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { template<class T> class CircularArray : protected Array<T> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef typename Array<T>::value_type value_type; typedef typename Array<T>::reference reference; typedef typename Array<T>::pointer_type pointer_type; typedef typename Array<T>::const_reference const_reference; /// Allocation of a new array with a default value CircularArray(UInt size, UInt nb_component = 1, const_reference value = value_type(), const ID & id = "") : Array<T>(size, nb_component, value, id), start_position(0), end_position(size-1) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); }; virtual ~CircularArray() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); }; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /** advance start and end position by one: the first element is now at the end of the array **/ inline void makeStep(); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; private: /* ------------------------------------------------------------------------ */ /* Operators */ /* ------------------------------------------------------------------------ */ public: inline reference operator()(UInt i, UInt j = 0); inline const_reference operator()(UInt i, UInt j = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: UInt getSize() const{ return this->size; }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// indice of first element in this circular array UInt start_position; /// indice of last element in this circular array UInt end_position; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "aka_circular_array_inline_impl.cc" #endif /// standard output stream operator template <typename T> inline std::ostream & operator <<(std::ostream & stream, const CircularArray<T> & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_AKA_CIRCULAR_ARRAY_HH__ */ diff --git a/src/common/aka_common.cc b/src/common/aka_common.cc index 51708f754..dd5955a94 100644 --- a/src/common/aka_common.cc +++ b/src/common/aka_common.cc @@ -1,155 +1,155 @@ /** * @file aka_common.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Jun 14 2010 * @date last modification: Tue Jan 19 2016 * * @brief Initialization of global variables * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_static_memory.hh" #include "static_communicator.hh" #include "aka_random_generator.hh" #include "parser.hh" #include "cppargparse.hh" #include "communication_tag.hh" /* -------------------------------------------------------------------------- */ #include <ctime> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ void initialize(int & argc, char **& argv) { AKANTU_DEBUG_IN(); initialize("", argc, argv); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void initialize(const std::string & input_file, int & argc, char **& argv) { AKANTU_DEBUG_IN(); StaticMemory::getStaticMemory(); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(argc, argv); Tag::setMaxTag(comm.getMaxTag()); debug::debugger.setParallelContext(comm.whoAmI(), comm.getNbProc()); debug::initSignalHandler(); debug::setDebugLevel(dblError); static_argparser.setParallelContext(comm.whoAmI(), comm.getNbProc()); static_argparser.setExternalExitFunction(debug::exit); static_argparser.addArgument("--aka_input_file", "Akantu's input file", 1, cppargparse::_string, std::string()); static_argparser.addArgument( "--aka_debug_level", std::string("Akantu's overall debug level") + std::string(" (0: error, 1: exceptions, 4: warnings, 5: info, ..., " "100: dump") + std::string(" more info on levels can be foind in aka_error.hh)"), 1, cppargparse::_integer, int(dblWarning)); static_argparser.addArgument( "--aka_print_backtrace", "Should Akantu print a backtrace in case of error", 0, cppargparse::_boolean, false, true); static_argparser.parse(argc, argv, cppargparse::_remove_parsed); std::string infile = static_argparser["aka_input_file"]; if (infile == "") infile = input_file; debug::debugger.printBacktrace(static_argparser["aka_print_backtrace"]); if ("" != infile) { readInputFile(infile); } long int seed; try { seed = static_parser.getParameter("seed", _ppsc_current_scope); } catch (debug::Exception &) { seed = time(NULL); } seed *= (comm.whoAmI() + 1); #if not defined(_WIN32) Rand48Generator<Real>::seed(seed); #endif RandGenerator<Real>::seed(seed); int dbl_level = static_argparser["aka_debug_level"]; debug::setDebugLevel(DebugLevel(dbl_level)); AKANTU_DEBUG_INFO("Random seed set to " << seed); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void finalize() { AKANTU_DEBUG_IN(); if (StaticCommunicator::isInstantiated()) { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); delete &comm; } if (StaticMemory::isInstantiated()) { delete &(StaticMemory::getStaticMemory()); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void readInputFile(const std::string & input_file) { static_parser.parse(input_file); } /* -------------------------------------------------------------------------- */ cppargparse::ArgumentParser & getStaticArgumentParser() { return static_argparser; } /* -------------------------------------------------------------------------- */ Parser & getStaticParser() { return static_parser; } /* -------------------------------------------------------------------------- */ const ParserSection & getUserParser() { return *(static_parser.getSubSections(_st_user).first); } -__END_AKANTU__ +} // akantu diff --git a/src/common/aka_common.hh b/src/common/aka_common.hh index e4a818674..306b774a0 100644 --- a/src/common/aka_common.hh +++ b/src/common/aka_common.hh @@ -1,447 +1,447 @@ /** * @file aka_common.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Jun 14 2010 * @date last modification: Thu Jan 21 2016 * * @brief common type descriptions for akantu * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * * @section DESCRIPTION * * All common things to be included in the projects files * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_COMMON_HH__ #define __AKANTU_COMMON_HH__ /* -------------------------------------------------------------------------- */ #include <list> #include <limits> #include <type_traits> #if __cplusplus < 201402L namespace std { template< bool B, class T = void > using enable_if_t = typename enable_if<B,T>::type; } #endif /* -------------------------------------------------------------------------- */ -#define __BEGIN_AKANTU__ namespace akantu { -#define __END_AKANTU__ } +#define namespace akantu { namespace akantu { +#define } // akantu } /* -------------------------------------------------------------------------- */ #define __BEGIN_AKANTU_DUMPER__ namespace dumper { #define __END_AKANTU_DUMPER__ } /* -------------------------------------------------------------------------- */ #if defined(WIN32) #define __attribute__(x) #endif /* -------------------------------------------------------------------------- */ #include "aka_config.hh" #include "aka_error.hh" #include "aka_safe_enum.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* Common types */ /* -------------------------------------------------------------------------- */ using ID = std::string; #ifdef AKANTU_NDEBUG static const Real REAL_INIT_VALUE = Real(0.); #else static const Real REAL_INIT_VALUE = std::numeric_limits<Real>::quiet_NaN(); #endif /* -------------------------------------------------------------------------- */ /* Memory types */ /* -------------------------------------------------------------------------- */ using MemoryID = UInt; using Surface = std::string; typedef std::pair<Surface, Surface> SurfacePair; using SurfacePairList = std::list<SurfacePair>; /* -------------------------------------------------------------------------- */ extern const UInt _all_dimensions; /* -------------------------------------------------------------------------- */ /* Mesh/FEM/Model types */ /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #include "aka_element_classes_info.hh" -__BEGIN_AKANTU__ +namespace akantu { /// small help to use names for directions enum SpacialDirection { _x = 0, _y = 1, _z = 2 }; /// enum MeshIOType type of mesh reader/writer enum MeshIOType { _miot_auto, ///< Auto guess of the reader to use based on the extension _miot_gmsh, ///< Gmsh files _miot_gmsh_struct, ///< Gsmh reader with reintpretation of elements has /// structures elements _miot_diana, ///< TNO Diana mesh format _miot_abaqus ///< Abaqus mesh format }; /// enum AnalysisMethod type of solving method used to solve the equation of /// motion enum AnalysisMethod { _static = 0, _implicit_dynamic = 1, _explicit_lumped_mass = 2, _explicit_lumped_capacity = 2, _explicit_consistent_mass = 3 }; /// enum DOFSupportType defines which kind of dof that can exists enum DOFSupportType { _dst_nodal, _dst_generic }; /// Type of non linear resolution available in akantu enum NonLinearSolverType { _nls_linear, ///< No non linear convergence loop _nls_newton_raphson, ///< Regular Newton-Raphson _nls_newton_raphson_modified, ///< Newton-Raphson with initial tangent _nls_lumped, ///< Case of lumped mass or equivalent matrix _nls_auto ///< This will take a default value that make sense in case of /// model::getNewSolver }; /// Define the node/dof type enum NodeType : Int { _nt_pure_gost = -3, _nt_master = -2, _nt_normal = -1 }; /// Type of time stepping solver enum TimeStepSolverType { _tsst_static, ///< Static solution _tsst_dynamic, ///< Dynamic solver _tsst_dynamic_lumped, ///< Dynamic solver with lumped mass }; /// Type of integration scheme enum IntegrationSchemeType { _ist_pseudo_time, ///< Pseudo Time _ist_forward_euler, ///< GeneralizedTrapezoidal(0) _ist_trapezoidal_rule_1, ///< GeneralizedTrapezoidal(1/2) _ist_backward_euler, ///< GeneralizedTrapezoidal(1) _ist_central_difference, ///< NewmarkBeta(0, 1/2) _ist_fox_goodwin, ///< NewmarkBeta(1/6, 1/2) _ist_trapezoidal_rule_2, ///< NewmarkBeta(1/2, 1/2) _ist_linear_acceleration, ///< NewmarkBeta(1/3, 1/2) _ist_newmark_beta, ///< generic NewmarkBeta with user defined /// alpha and beta _ist_generalized_trapezoidal ///< generic GeneralizedTrapezoidal with user /// defined alpha }; /// enum SolveConvergenceCriteria different convergence criteria enum SolveConvergenceCriteria { _scc_residual, ///< Use residual to test the convergence _scc_solution, ///< Use solution to test the convergence _scc_residual_mass_wgh ///< Use residual weighted by inv. nodal mass to testb }; /// enum CohesiveMethod type of insertion of cohesive elements enum CohesiveMethod { _intrinsic, _extrinsic }; /// @enum SparseMatrixType type of sparse matrix used enum MatrixType { _unsymmetric, _symmetric }; /* -------------------------------------------------------------------------- */ /* Ghosts handling */ /* -------------------------------------------------------------------------- */ using SynchronizerID = ID; /// @enum CommunicatorType type of communication method to use enum CommunicatorType { _communicator_mpi, _communicator_dummy }; /// @enum SynchronizationTag type of synchronizations enum SynchronizationTag { //--- Generic tags --- _gst_whatever, _gst_update, _gst_size, //--- SolidMechanicsModel tags --- _gst_smm_mass, ///< synchronization of the SolidMechanicsModel.mass _gst_smm_for_gradu, ///< synchronization of the /// SolidMechanicsModel.displacement _gst_smm_boundary, ///< synchronization of the boundary, forces, velocities /// and displacement _gst_smm_uv, ///< synchronization of the nodal velocities and displacement _gst_smm_res, ///< synchronization of the nodal residual _gst_smm_init_mat, ///< synchronization of the data to initialize materials _gst_smm_stress, ///< synchronization of the stresses to compute the internal /// forces _gst_smmc_facets, ///< synchronization of facet data to setup facet synch _gst_smmc_facets_conn, ///< synchronization of facet global connectivity _gst_smmc_facets_stress, ///< synchronization of facets' stress to setup facet /// synch _gst_smmc_damage, ///< synchronization of damage // --- GlobalIdsUpdater tags --- _gst_giu_global_conn, ///< synchronization of global connectivities // --- CohesiveElementInserter tags --- _gst_ce_groups, ///< synchronization of cohesive element insertion depending /// on facet groups // --- GroupManager tags --- _gst_gm_clusters, ///< synchronization of clusters // --- 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 // --- LevelSet tags --- _gst_htm_phi, ///< synchronization of the nodal level set value phi _gst_htm_gradient_phi, ///< synchronization of the element gradient phi //--- Material non local --- _gst_mnl_for_average, ///< synchronization of data to average in non local /// material _gst_mnl_weight, ///< synchronization of data for the weight computations // --- NeighborhoodSynchronization tags --- _gst_nh_criterion, // --- General tags --- _gst_test, ///< Test tag _gst_user_1, ///< tag for user simulations _gst_user_2, ///< tag for user simulations _gst_material_id, ///< synchronization of the material ids _gst_for_dump, ///< everything that needs to be synch before dump // --- Contact & Friction --- _gst_cf_nodal, ///< synchronization of disp, velo, and current position _gst_cf_incr, ///< synchronization of increment // --- Solver tags --- _gst_solver_solution ///< synchronization of the solution obained with the /// PETSc solver }; /// standard output stream operator for SynchronizationTag inline std::ostream & operator<<(std::ostream & stream, SynchronizationTag type); /// @enum GhostType type of ghost enum GhostType { _not_ghost, _ghost, _casper // not used but a real cute ghost }; /* -------------------------------------------------------------------------- */ struct GhostType_def { using type = GhostType; static const type _begin_ = _not_ghost; static const type _end_ = _casper; }; using ghost_type_t = safe_enum<GhostType_def>; extern ghost_type_t ghost_types; /// standard output stream operator for GhostType inline std::ostream & operator<<(std::ostream & stream, GhostType type); /// @enum SynchronizerOperation reduce operation that the synchronizer can /// perform enum SynchronizerOperation { _so_sum, _so_min, _so_max, _so_prod, _so_land, _so_band, _so_lor, _so_bor, _so_lxor, _so_bxor, _so_min_loc, _so_max_loc, _so_null }; /* -------------------------------------------------------------------------- */ /* Global defines */ /* -------------------------------------------------------------------------- */ #define AKANTU_MIN_ALLOCATION 2000 #define AKANTU_INDENT " " #define AKANTU_INCLUDE_INLINE_IMPL /* -------------------------------------------------------------------------- */ template <class T> struct is_scalar { enum { value = false }; }; #define AKANTU_SPECIFY_IS_SCALAR(type) \ template <> struct is_scalar<type> { \ enum { value = true }; \ } AKANTU_SPECIFY_IS_SCALAR(Real); AKANTU_SPECIFY_IS_SCALAR(UInt); AKANTU_SPECIFY_IS_SCALAR(Int); AKANTU_SPECIFY_IS_SCALAR(bool); template <typename T1, typename T2> struct is_same { enum { value = false }; // is_same represents a bool. }; template <typename T> struct is_same<T, T> { enum { value = true }; }; /* -------------------------------------------------------------------------- */ #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_SUPPORT_TYPE(name, variable, type, support, con) \ inline con Array<type> & get##name( \ const support & el_type, const GhostType & ghost_type = _not_ghost) \ con { \ return variable(el_type, ghost_type); \ } #define AKANTU_GET_MACRO_BY_ELEMENT_TYPE(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, ElementType, ) #define AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, ElementType, const) #define AKANTU_GET_MACRO_BY_GEOMETRIE_TYPE(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, GeometricalType, ) #define AKANTU_GET_MACRO_BY_GEOMETRIE_TYPE_CONST(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, GeometricalType, const) /* -------------------------------------------------------------------------- */ /// initialize the static part of akantu void initialize(int & argc, char **& argv); /// initialize the static part of akantu and read the global input_file void initialize(const std::string & input_file, int & argc, char **& argv); /* -------------------------------------------------------------------------- */ /// finilize correctly akantu and clean the memory void finalize(); /* -------------------------------------------------------------------------- */ /// Read an new input file void readInputFile(const std::string & input_file); /* -------------------------------------------------------------------------- */ /* * 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 std::string to_lower(const std::string & str); /* -------------------------------------------------------------------------- */ inline std::string trim(const std::string & to_trim); /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /// give a string representation of the a human readable size in bit template <typename T> std::string printMemorySize(UInt size); /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #include "aka_fwd.hh" -__BEGIN_AKANTU__ +namespace akantu { /// get access to the internal argument parser cppargparse::ArgumentParser & getStaticArgumentParser(); /// get access to the internal input file parser Parser & getStaticParser(); /// get access to the user part of the internal input file parser const ParserSection & getUserParser(); -__END_AKANTU__ +} // akantu #include "aka_common_inline_impl.cc" /* -------------------------------------------------------------------------- */ #if AKANTU_INTEGER_SIZE == 4 #define AKANTU_HASH_COMBINE_MAGIC_NUMBER 0x9e3779b9 #elif AKANTU_INTEGER_SIZE == 8 #define AKANTU_HASH_COMBINE_MAGIC_NUMBER 0x9e3779b97f4a7c13LL #endif namespace std { /** * Hashing function for pairs based on hash_combine from boost The magic number * is coming from the golden number @f[\phi = \frac{1 + \sqrt5}{2}@f] * @f[\frac{2^32}{\phi} = 0x9e3779b9@f] * http://stackoverflow.com/questions/4948780/magic-number-in-boosthash-combine * http://burtleburtle.net/bob/hash/doobs.html */ template <typename a, typename b> struct hash<std::pair<a, b> > { public: hash() : ah(), bh() {} size_t operator()(const std::pair<a, b> & p) const { size_t seed = ah(p.first); return bh(p.second) + AKANTU_HASH_COMBINE_MAGIC_NUMBER + (seed << 6) + (seed >> 2); } private: const hash<a> ah; const hash<b> bh; }; } //std #endif /* __AKANTU_COMMON_HH__ */ diff --git a/src/common/aka_common_inline_impl.cc b/src/common/aka_common_inline_impl.cc index 23509586e..820bb02c1 100644 --- a/src/common/aka_common_inline_impl.cc +++ b/src/common/aka_common_inline_impl.cc @@ -1,456 +1,456 @@ /** * @file aka_common_inline_impl.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 15 2015 * * @brief inline implementations of common akantu type descriptions * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * * @section DESCRIPTION * * All common things to be included in the projects files * */ /* -------------------------------------------------------------------------- */ #include <algorithm> #include <cctype> #include <iomanip> #include <iostream> #include "aka_common.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_COMMON_INLINE_IMPL_CC__ #define __AKANTU_AKA_COMMON_INLINE_IMPL_CC__ namespace akantu { /* -------------------------------------------------------------------------- */ /// 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; } /* -------------------------------------------------------------------------- */ /// standard output stream operator for TimeStepSolverType inline std::ostream & operator<<(std::ostream & stream, const TimeStepSolverType & type) { switch (type) { case _tsst_static: stream << "static"; break; case _tsst_dynamic: stream << "dynamic"; break; case _tsst_dynamic_lumped: stream << "dynamic_lumped"; break; } return stream; } /* -------------------------------------------------------------------------- */ /// standard input stream operator for TimeStepSolverType inline std::istream & operator>>(std::istream & stream, TimeStepSolverType & type) { std::string str; stream >> str; if (str == "static") type = _tsst_static; else if (str == "dynamic") type = _tsst_dynamic; else if (str == "dynamic_lumped") type = _tsst_dynamic_lumped; else { AKANTU_DEBUG_ERROR("The type " << str << " is not a recognized TimeStepSolverType"); stream.setstate(std::ios::failbit); } return stream; } /* -------------------------------------------------------------------------- */ /// standard output stream operator for NonLinearSolverType inline std::ostream & operator<<(std::ostream & stream, const NonLinearSolverType & type) { switch (type) { case _nls_linear: stream << "linear"; break; case _nls_newton_raphson: stream << "newton_raphson"; break; case _nls_newton_raphson_modified: stream << "newton_raphson_modified"; break; case _nls_lumped: stream << "lumped"; break; case _nls_auto: stream << "auto"; break; } return stream; } /* -------------------------------------------------------------------------- */ /// standard input stream operator for NonLinearSolverType inline std::istream & operator>>(std::istream & stream, NonLinearSolverType & type) { std::string str; stream >> str; if (str == "linear") type = _nls_linear; else if (str == "newton_raphson") type = _nls_newton_raphson; else if (str == "newton_raphson_modified") type = _nls_newton_raphson_modified; else if (str == "lumped") type = _nls_lumped; else if (str == "auto") type = _nls_auto; else type = _nls_auto; return stream; } /* -------------------------------------------------------------------------- */ /// standard output stream operator for IntegrationSchemeType inline std::ostream & operator<<(std::ostream & stream, const IntegrationSchemeType & type) { switch (type) { case _ist_pseudo_time: stream << "pseudo_time"; break; case _ist_forward_euler: stream << "forward_euler"; break; case _ist_trapezoidal_rule_1: stream << "trapezoidal_rule_1"; break; case _ist_backward_euler: stream << "backward_euler"; break; case _ist_central_difference: stream << "central_difference"; break; case _ist_fox_goodwin: stream << "fox_goodwin"; break; case _ist_trapezoidal_rule_2: stream << "trapezoidal_rule_2"; break; case _ist_linear_acceleration: stream << "linear_acceleration"; break; case _ist_newmark_beta: stream << "newmark_beta"; break; case _ist_generalized_trapezoidal: stream << "generalized_trapezoidal"; break; } return stream; } /* -------------------------------------------------------------------------- */ /// standard input stream operator for IntegrationSchemeType inline std::istream & operator>>(std::istream & stream, IntegrationSchemeType & type) { std::string str; stream >> str; if (str == "pseudo_time") type = _ist_pseudo_time; else if (str == "forward_euler") type = _ist_forward_euler; else if (str == "trapezoidal_rule_1") type = _ist_trapezoidal_rule_1; else if (str == "backward_euler") type = _ist_backward_euler; else if (str == "central_difference") type = _ist_central_difference; else if (str == "fox_goodwin") type = _ist_fox_goodwin; else if (str == "trapezoidal_rule_2") type = _ist_trapezoidal_rule_2; else if (str == "linear_acceleration") type = _ist_linear_acceleration; else if (str == "newmark_beta") type = _ist_newmark_beta; else if (str == "generalized_trapezoidal") type = _ist_generalized_trapezoidal; else { AKANTU_DEBUG_ERROR("The type " << str << " is not a recognized IntegrationSchemeType"); stream.setstate(std::ios::failbit); } return stream; } /* -------------------------------------------------------------------------- */ /// standard output stream operator for SynchronizationTag inline std::ostream & operator<<(std::ostream & stream, SynchronizationTag type) { switch (type) { case _gst_whatever: stream << "_gst_whatever"; break; case _gst_update: stream << "_gst_update"; break; case _gst_size: stream << "_gst_size"; break; case _gst_smm_mass: stream << "_gst_smm_mass"; break; case _gst_smm_for_gradu: stream << "_gst_smm_for_gradu"; break; case _gst_smm_boundary: stream << "_gst_smm_boundary"; break; case _gst_smm_uv: stream << "_gst_smm_uv"; break; case _gst_smm_res: stream << "_gst_smm_res"; break; case _gst_smm_init_mat: stream << "_gst_smm_init_mat"; break; case _gst_smm_stress: stream << "_gst_smm_stress"; break; case _gst_smmc_facets: stream << "_gst_smmc_facets"; break; case _gst_smmc_facets_conn: stream << "_gst_smmc_facets_conn"; break; case _gst_smmc_facets_stress: stream << "_gst_smmc_facets_stress"; break; case _gst_smmc_damage: stream << "_gst_smmc_damage"; break; case _gst_giu_global_conn: stream << "_gst_giu_global_conn"; break; case _gst_ce_groups: stream << "_gst_ce_groups"; break; case _gst_gm_clusters: stream << "_gst_gm_clusters"; break; case _gst_htm_capacity: stream << "_gst_htm_capacity"; break; case _gst_htm_temperature: stream << "_gst_htm_temperature"; break; case _gst_htm_gradient_temperature: stream << "_gst_htm_gradient_temperature"; break; case _gst_htm_phi: stream << "_gst_htm_phi"; break; case _gst_htm_gradient_phi: stream << "_gst_htm_gradient_phi"; break; case _gst_mnl_for_average: stream << "_gst_mnl_for_average"; break; case _gst_mnl_weight: stream << "_gst_mnl_weight"; break; case _gst_nh_criterion: stream << "_gst_nh_criterion"; break; case _gst_test: stream << "_gst_test"; break; case _gst_user_1: stream << "_gst_user_1"; break; case _gst_user_2: stream << "_gst_user_2"; break; case _gst_material_id: stream << "_gst_material_id"; break; case _gst_for_dump: stream << "_gst_for_dump"; break; case _gst_cf_nodal: stream << "_gst_cf_nodal"; break; case _gst_cf_incr: stream << "_gst_cf_incr"; break; case _gst_solver_solution: stream << "_gst_solver_solution"; break; } return stream; } /* -------------------------------------------------------------------------- */ /// standard output stream operator for SolveConvergenceCriteria inline std::ostream & operator<<(std::ostream & stream, const SolveConvergenceCriteria & criteria) { switch (criteria) { case _scc_residual: stream << "_scc_residual"; break; case _scc_solution: stream << "_scc_solution"; break; case _scc_residual_mass_wgh: stream << "_scc_residual_mass_wgh"; break; } return stream; } inline std::istream & operator>>(std::istream & stream, SolveConvergenceCriteria & criteria) { std::string str; stream >> str; if (str == "residual") criteria = _scc_residual; else if (str == "solution") criteria = _scc_solution; else if (str == "residual_mass_wgh") criteria = _scc_residual_mass_wgh; else { stream.setstate(std::ios::failbit); } return stream; } /* -------------------------------------------------------------------------- */ inline std::string to_lower(const std::string & str) { std::string lstr = str; std::transform(lstr.begin(), lstr.end(), lstr.begin(), (int (*)(int))tolower); return lstr; } /* -------------------------------------------------------------------------- */ inline std::string trim(const std::string & to_trim) { std::string trimed = to_trim; // left trim trimed.erase(trimed.begin(), std::find_if(trimed.begin(), trimed.end(), std::not1(std::ptr_fun<int, int>(isspace)))); // right trim trimed.erase(std::find_if(trimed.rbegin(), trimed.rend(), std::not1(std::ptr_fun<int, int>(isspace))) .base(), trimed.end()); return trimed; } -__END_AKANTU__ +} // akantu #include <cmath> -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <typename T> std::string printMemorySize(UInt size) { Real real_size = size * sizeof(T); UInt mult = 0; if (real_size != 0) mult = (std::log(real_size) / std::log(2)) / 10; std::stringstream sstr; real_size /= Real(1 << (10 * mult)); sstr << std::setprecision(2) << std::fixed << real_size; std::string size_prefix; switch (mult) { case 0: sstr << ""; break; case 1: sstr << "Ki"; break; case 2: sstr << "Mi"; break; case 3: sstr << "Gi"; break; // I started on this type of machines // (32bit computers) (Nicolas) case 4: sstr << "Ti"; break; case 5: sstr << "Pi"; break; case 6: sstr << "Ei"; break; // theoritical limit of RAM of the current // computers in 2014 (64bit computers) (Nicolas) case 7: sstr << "Zi"; break; case 8: sstr << "Yi"; break; default: AKANTU_DEBUG_ERROR( "The programmer in 2014 didn't thought so far (even wikipedia does not " "go further)." << " You have at least 1024 times more than a yobibit of RAM!!!" << " Just add the prefix corresponding in this switch case."); } sstr << "Byte"; return sstr.str(); } } // akantu #endif /* __AKANTU_AKA_COMMON_INLINE_IMPL_CC__ */ diff --git a/src/common/aka_csr.hh b/src/common/aka_csr.hh index 464e5ec2f..9e2d72a0b 100644 --- a/src/common/aka_csr.hh +++ b/src/common/aka_csr.hh @@ -1,259 +1,259 @@ /** * @file aka_csr.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Apr 20 2011 * @date last modification: Sun Oct 19 2014 * * @brief A compresed sparse row structure based on akantu Arrays * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" #include "aka_common.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_CSR_HH__ #define __AKANTU_AKA_CSR_HH__ -__BEGIN_AKANTU__ +namespace akantu { /** * This class can be used to store the structure of a sparse matrix or for * vectors with variable number of component per element * * @param nb_rows number of rows of a matrix or size of a vector. */ template <typename T> class CSR { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: explicit CSR(UInt nb_rows = 0) : nb_rows(nb_rows), rows_offsets(nb_rows + 1, 1, "rows_offsets"), rows(0, 1, "rows") { rows_offsets.clear(); }; virtual ~CSR(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// does nothing inline void beginInsertions(){}; /// insert a new entry val in row row inline UInt insertInRow(UInt row, const T & val) { UInt pos = rows_offsets(row)++; rows(pos) = val; return pos; } /// access an element of the matrix inline const T & operator()(UInt row, UInt col) const { AKANTU_DEBUG_ASSERT(rows_offsets(row + 1) - rows_offsets(row) > col, "This element is not present in this CSR"); return rows(rows_offsets(row) + col); } /// access an element of the matrix inline T & operator()(UInt row, UInt col) { AKANTU_DEBUG_ASSERT(rows_offsets(row + 1) - rows_offsets(row) > col, "This element is not present in this CSR"); return rows(rows_offsets(row) + col); } inline void endInsertions() { for (UInt i = nb_rows; i > 0; --i) rows_offsets(i) = rows_offsets(i - 1); rows_offsets(0) = 0; } inline void countToCSR() { for (UInt i = 1; i < nb_rows; ++i) rows_offsets(i) += rows_offsets(i - 1); for (UInt i = nb_rows; i >= 1; --i) rows_offsets(i) = rows_offsets(i - 1); rows_offsets(0) = 0; } inline void clearRows() { rows_offsets.clear(); rows.resize(0); }; inline void resizeRows(UInt nb_rows) { this->nb_rows = nb_rows; rows_offsets.resize(nb_rows + 1); rows_offsets.clear(); } inline void resizeCols() { rows.resize(rows_offsets(nb_rows)); } inline void copy(Array<UInt> & offsets, Array<T> & values) { offsets.copy(rows_offsets); values.copy(rows); } /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// returns the number of rows inline UInt getNbRows() const { return rows_offsets.getSize() - 1; }; /// returns the number of non-empty columns in a given row inline UInt getNbCols(UInt row) const { return rows_offsets(row + 1) - rows_offsets(row); }; /// returns the offset (start of columns) for a given row inline UInt & rowOffset(UInt row) { return rows_offsets(row); }; /// iterator on a row template <class R> class iterator_internal : public std::iterator<std::bidirectional_iterator_tag, R> { public: typedef std::iterator<std::bidirectional_iterator_tag, R> _parent; typedef typename _parent::pointer pointer; typedef typename _parent::reference reference; explicit iterator_internal(pointer x = NULL) : pos(x){}; iterator_internal(const iterator_internal & it) : pos(it.pos){}; iterator_internal & operator++() { ++pos; return *this; }; iterator_internal operator++(int) { iterator tmp(*this); operator++(); return tmp; }; iterator_internal & operator--() { --pos; return *this; }; iterator_internal operator--(int) { iterator_internal tmp(*this); operator--(); return tmp; }; bool operator==(const iterator_internal & rhs) { return pos == rhs.pos; }; bool operator!=(const iterator_internal & rhs) { return pos != rhs.pos; }; reference operator*() { return *pos; }; pointer operator->() const { return pos; }; private: pointer pos; }; typedef iterator_internal<T> iterator; typedef iterator_internal<const T> const_iterator; inline iterator begin(UInt row) { return iterator(rows.storage() + rows_offsets(row)); }; inline iterator end(UInt row) { return iterator(rows.storage() + rows_offsets(row + 1)); }; inline const_iterator begin(UInt row) const { return const_iterator(rows.storage() + rows_offsets(row)); }; inline const_iterator end(UInt row) const { return const_iterator(rows.storage() + rows_offsets(row + 1)); }; inline iterator rbegin(UInt row) { return iterator(rows.storage() + rows_offsets(row + 1) - 1); }; inline iterator rend(UInt row) { return iterator(rows.storage() + rows_offsets(row) - 1); }; inline const Array<UInt> & getRowsOffset() const { return rows_offsets; }; inline const Array<T> & getRows() const { return rows; }; inline Array<T> & getRows() { return rows; }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: UInt nb_rows; /// array of size nb_rows containing the offset where the values are stored in Array<UInt> rows_offsets; /// compressed row values, values of row[i] are stored between rows_offsets[i] /// and rows_offsets[i+1] Array<T> rows; }; /* -------------------------------------------------------------------------- */ /* Data CSR */ /* -------------------------------------------------------------------------- */ /** * Inherits from CSR<UInt> and can contain information such as matrix values * where the mother class would be a CSR structure for row and cols * * @return nb_rows */ template <class T> class DataCSR : public CSR<UInt> { public: DataCSR(UInt nb_rows = 0) : CSR<UInt>(nb_rows), data(0, 1){}; inline void resizeCols() { CSR<UInt>::resizeCols(); data.resize(rows_offsets(nb_rows)); } inline const Array<T> & getData() const { return data; }; private: Array<T> data; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "aka_csr_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const CSR & _this) // { // _this.printself(stream); // return stream; // } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_AKA_CSR_HH__ */ diff --git a/src/common/aka_element_classes_info.hh.in b/src/common/aka_element_classes_info.hh.in index e71f120fc..8f7511918 100644 --- a/src/common/aka_element_classes_info.hh.in +++ b/src/common/aka_element_classes_info.hh.in @@ -1,199 +1,199 @@ /** * @file aka_element_classes_info.hh.in * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sun Jul 19 2015 * @date last modification: Fri Oct 16 2015 * * @brief Declaration of the enums for the element classes * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <boost/preprocessor.hpp> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* Element Types */ /* -------------------------------------------------------------------------- */ /// @enum ElementType type of elements enum ElementType { _not_defined, @AKANTU_ELEMENT_TYPES_ENUM@ _max_element_type }; @AKANTU_ELEMENT_TYPES_BOOST_SEQ@ @AKANTU_ALL_ELEMENT_BOOST_SEQ@ /* -------------------------------------------------------------------------- */ /* Element Kinds */ /* -------------------------------------------------------------------------- */ @AKANTU_ELEMENT_KINDS_BOOST_SEQ@ @AKANTU_ELEMENT_KIND_BOOST_SEQ@ #ifndef SWIG enum ElementKind { BOOST_PP_SEQ_ENUM(AKANTU_ELEMENT_KIND), _ek_not_defined }; /* -------------------------------------------------------------------------- */ struct ElementKind_def { using type = ElementKind; static const type _begin_ = BOOST_PP_SEQ_HEAD(AKANTU_ELEMENT_KIND); static const type _end_ = _ek_not_defined; }; using element_kind_t = safe_enum<ElementKind_def> ; #else enum ElementKind; #endif /* -------------------------------------------------------------------------- */ /// @enum GeometricalType type of element potentially contained in a Mesh enum GeometricalType { @AKANTU_GEOMETRICAL_TYPES_ENUM@ _gt_not_defined }; /* -------------------------------------------------------------------------- */ /* Interpolation Types */ /* -------------------------------------------------------------------------- */ @AKANTU_INTERPOLATION_TYPES_BOOST_SEQ@ #ifndef SWIG /// @enum InterpolationType type of elements enum InterpolationType { BOOST_PP_SEQ_ENUM(AKANTU_INTERPOLATION_TYPES), _itp_not_defined }; #else enum InterpolationType; #endif /* -------------------------------------------------------------------------- */ /* Some sub types less probable to change */ /* -------------------------------------------------------------------------- */ /// @enum GeometricalShapeType types of shapes to define the contains /// function in the element classes enum GeometricalShapeType { @AKANTU_GEOMETRICAL_SHAPES_ENUM@ _gst_not_defined }; /* -------------------------------------------------------------------------- */ /// @enum GaussIntegrationType classes of types using common /// description of the gauss point position and weights enum GaussIntegrationType { @AKANTU_GAUSS_INTEGRATION_TYPES_ENUM@ _git_not_defined }; /* -------------------------------------------------------------------------- */ /// @enum InterpolationKind the family of interpolation types enum InterpolationKind { @AKANTU_INTERPOLATION_KIND_ENUM@ _itk_not_defined }; /* -------------------------------------------------------------------------- */ // BOOST PART: TOUCH ONLY IF YOU KNOW WHAT YOU ARE DOING #define AKANTU_BOOST_CASE_MACRO(r,macro,_type) \ case _type : { macro(_type); break; } #define AKANTU_BOOST_LIST_SWITCH(macro1, list1, var) \ do { \ switch(var) { \ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO, macro1, list1) \ default: { \ AKANTU_DEBUG_ERROR("Type (" << var << ") not handled by this function"); \ } \ } \ } while(0) #define AKANTU_BOOST_ELEMENT_SWITCH(macro1, list1) \ AKANTU_BOOST_LIST_SWITCH(macro1, list1, type) #define AKANTU_BOOST_ALL_ELEMENT_SWITCH(macro) \ AKANTU_BOOST_ELEMENT_SWITCH(macro, \ AKANTU_ALL_ELEMENT_TYPE) #define AKANTU_BOOST_LIST_MACRO(r, macro, type) \ macro(type) #define AKANTU_BOOST_APPLY_ON_LIST(macro, list) \ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_LIST_MACRO, macro, list) #define AKANTU_BOOST_ALL_ELEMENT_LIST(macro) \ AKANTU_BOOST_APPLY_ON_LIST(macro, \ AKANTU_ALL_ELEMENT_TYPE) #define AKANTU_GET_ELEMENT_LIST(kind) \ AKANTU##kind##_ELEMENT_TYPE #define AKANTU_BOOST_KIND_ELEMENT_SWITCH(macro, kind) \ AKANTU_BOOST_ELEMENT_SWITCH(macro, \ AKANTU_GET_ELEMENT_LIST(kind)) // BOOST_PP_SEQ_TO_LIST does not exists in Boost < 1.49 #define AKANTU_GENERATE_KIND_LIST(seq) \ BOOST_PP_TUPLE_TO_LIST(BOOST_PP_SEQ_SIZE(seq), \ BOOST_PP_SEQ_TO_TUPLE(seq)) #define AKANTU_ELEMENT_KIND_BOOST_LIST AKANTU_GENERATE_KIND_LIST(AKANTU_ELEMENT_KIND) #define AKANTU_BOOST_ALL_KIND_LIST(macro, list) \ BOOST_PP_LIST_FOR_EACH(AKANTU_BOOST_LIST_MACRO, macro, list) #define AKANTU_BOOST_ALL_KIND(macro) \ AKANTU_BOOST_ALL_KIND_LIST(macro, AKANTU_ELEMENT_KIND_BOOST_LIST) #define AKANTU_BOOST_ALL_KIND_SWITCH(macro) \ AKANTU_BOOST_LIST_SWITCH(macro, \ AKANTU_ELEMENT_KIND, \ kind) @AKANTU_ELEMENT_KINDS_BOOST_MACROS@ // /// define kept for compatibility reasons (they are most probably not needed // /// anymore) \todo check if they can be removed // #define AKANTU_REGULAR_ELEMENT_TYPE AKANTU_ek_regular_ELEMENT_TYPE // #define AKANTU_COHESIVE_ELEMENT_TYPE AKANTU_ek_cohesive_ELEMENT_TYPE // #define AKANTU_STRUCTURAL_ELEMENT_TYPE AKANTU_ek_structural_ELEMENT_TYPE // #define AKANTU_IGFEM_ELEMENT_TYPE AKANTU_ek_igfem_ELEMENT_TYPE /* -------------------------------------------------------------------------- */ /* Lists of interests for FEEngineTemplate functions */ /* -------------------------------------------------------------------------- */ @AKANTU_FE_ENGINE_LISTS@ -__END_AKANTU__ +} // akantu #include "aka_element_classes_info_inline_impl.cc" diff --git a/src/common/aka_element_classes_info_inline_impl.cc b/src/common/aka_element_classes_info_inline_impl.cc index e9d7877ec..39320f2fd 100644 --- a/src/common/aka_element_classes_info_inline_impl.cc +++ b/src/common/aka_element_classes_info_inline_impl.cc @@ -1,96 +1,96 @@ /** * @file aka_element_classes_info_inline_impl.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Jun 18 2015 * @date last modification: Sun Jul 19 2015 * * @brief Implementation of the streaming fonction for the element classes enums * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { #define STRINGIFY(type) \ stream << BOOST_PP_STRINGIZE(type) /* -------------------------------------------------------------------------- */ //! standard output stream operator for ElementType inline std::ostream & operator <<(std::ostream & stream, ElementType type) { switch(type) { BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO, \ STRINGIFY, \ AKANTU_ALL_ELEMENT_TYPE) case _not_defined: stream << "_not_defined"; break; case _max_element_type: stream << "_max_element_type"; break; } return stream; } /* -------------------------------------------------------------------------- */ //! standard input stream operator for ElementType inline std::istream & operator >>(std::istream & stream, ElementType & type) { #define IF_SEQUENCE(_type) \ else if (tmp == BOOST_PP_STRINGIZE(_type)) type = _type; std::string tmp; stream >> tmp; if (1 == 2) {} BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_LIST_MACRO, \ IF_SEQUENCE, \ AKANTU_ALL_ELEMENT_TYPE) else AKANTU_EXCEPTION("unknown element type: '" << tmp << "'"); #undef IF_SEQUENCE return stream; } /* -------------------------------------------------------------------------- */ //! standard output stream operator for ElementType inline std::ostream & operator <<(std::ostream & stream, ElementKind kind ) { AKANTU_BOOST_ALL_KIND_SWITCH(STRINGIFY); return stream; } /* -------------------------------------------------------------------------- */ /// standard output stream operator for InterpolationType inline std::ostream & operator <<(std::ostream & stream, InterpolationType type) { switch(type) { BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO, \ STRINGIFY, \ AKANTU_INTERPOLATION_TYPES) case _itp_not_defined : stream << "_itp_not_defined" ; break; } return stream; } #undef STRINGIFY -__END_AKANTU__ +} // akantu diff --git a/src/common/aka_event_handler_manager.hh b/src/common/aka_event_handler_manager.hh index 0d47d5c80..ae60d0671 100644 --- a/src/common/aka_event_handler_manager.hh +++ b/src/common/aka_event_handler_manager.hh @@ -1,129 +1,129 @@ /** * @file aka_event_handler_manager.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Wed Dec 16 2015 * * @brief Base of Event Handler classes * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_EVENT_HANDLER_MANAGER_HH__ #define __AKANTU_AKA_EVENT_HANDLER_MANAGER_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ #include <list> #include <algorithm> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { template <class EventHandler> class EventHandlerManager { private: typedef std::pair<UInt, EventHandler *> priority_value; typedef std::list<priority_value> priority_list; struct KeyComp { bool operator()(const priority_value & a, const priority_value & b) const { return (a.first < b.first); } bool operator()(const priority_value & a, UInt b) const { return (a.first < b); } }; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: virtual ~EventHandlerManager(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// register a new EventHandler to the Manager. The register object /// will then be informed about the events the manager observes. void registerEventHandler(EventHandler & event_handler, UInt priority = 100) { typename priority_list::iterator it = this->searchEventHandler(event_handler); if (it != this->event_handlers.end()) { AKANTU_EXCEPTION("This event handler was already registered"); } typename priority_list::iterator pos = std::lower_bound(this->event_handlers.begin(), this->event_handlers.end(), priority, KeyComp()); this->event_handlers.insert(pos, std::make_pair(priority, &event_handler)); } /// unregister a EventHandler object. This object will not be /// notified anymore about the events this manager observes. void unregisterEventHandler(EventHandler & event_handler) { typename priority_list::iterator it = this->searchEventHandler(event_handler); if (it == this->event_handlers.end()) { AKANTU_EXCEPTION("This event handler is not registered"); } this->event_handlers.erase(it); } /// Notify all the registered EventHandlers about the event that just occured. template <class Event> void sendEvent(const Event & event) { typename priority_list::iterator it = event_handlers.begin(); typename priority_list::iterator end = event_handlers.end(); for (; it != end; ++it) it->second->sendEvent(event); } private: typename priority_list::iterator searchEventHandler(EventHandler & handler) { typename priority_list::iterator it = this->event_handlers.begin(); typename priority_list::iterator end = this->event_handlers.end(); for (; it != end && it->second != &handler; ++it) ; return it; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// list of the event handlers priority_list event_handlers; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_AKA_EVENT_HANDLER_MANAGER_HH__ */ diff --git a/src/common/aka_grid_dynamic.hh b/src/common/aka_grid_dynamic.hh index c1758cf2f..b69b5700d 100644 --- a/src/common/aka_grid_dynamic.hh +++ b/src/common/aka_grid_dynamic.hh @@ -1,507 +1,507 @@ /** * @file aka_grid_dynamic.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Sat Sep 26 2015 * * @brief Grid that is auto balanced * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_array.hh" #include "aka_types.hh" #include <iostream> /* -------------------------------------------------------------------------- */ #include <map> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_GRID_DYNAMIC_HH__ #define __AKANTU_AKA_GRID_DYNAMIC_HH__ -__BEGIN_AKANTU__ +namespace akantu { class Mesh; template<typename T> class SpatialGrid { public: SpatialGrid(UInt dimension) : dimension(dimension), spacing(dimension), center(dimension), lower(dimension), upper(dimension), empty_cell() {} SpatialGrid(UInt dimension, const Vector<Real> & spacing, const Vector<Real> & center) : dimension(dimension), spacing(spacing), center(center), lower(dimension), upper(dimension), empty_cell() { for (UInt i = 0; i < dimension; ++i) { lower(i) = std::numeric_limits<Real>::max(); upper(i) = - std::numeric_limits<Real>::max(); } } virtual ~SpatialGrid() {}; class neighbor_cells_iterator; class cells_iterator; class CellID { public: CellID() : ids() {} CellID(UInt dimention) : ids(dimention) {} void setID(UInt dir, Int id) { ids(dir) = id; } Int getID(UInt dir) const { return ids(dir); } bool operator<(const CellID & id) const { return std::lexicographical_compare(ids.storage(), ids.storage() + ids.size(), id.ids.storage(), id.ids.storage() + id.ids.size()); } bool operator==(const CellID & id) const { return std::equal(ids.storage(), ids.storage() + ids.size(), id.ids.storage()); } bool operator!=(const CellID & id) const { return !(operator==(id)); } private: friend class neighbor_cells_iterator; friend class cells_iterator; Vector<Int> ids; }; /* -------------------------------------------------------------------------- */ class Cell { public: typedef typename std::vector<T>::iterator iterator; typedef typename std::vector<T>::const_iterator const_iterator; Cell() : id(), data() { } Cell(const CellID &cell_id) : id(cell_id), data() { } bool operator==(const Cell & cell) const { return id == cell.id; } bool operator!=(const Cell & cell) const { return id != cell.id; } Cell & add(const T & d) { data.push_back(d); return *this; } iterator begin() { return data.begin(); } const_iterator begin() const { return data.begin(); } iterator end() { return data.end(); } const_iterator end() const { return data.end(); } // #if not defined(AKANTU_NDEBUG) // Cell & add(const T & d, const Vector<Real> & pos) { // data.push_back(d); positions.push_back(pos); return *this; // } // typedef typename std::vector< Vector<Real> >::const_iterator position_iterator; // position_iterator begin_pos() const { return positions.begin(); } // position_iterator end_pos() const { return positions.end(); } // #endif private: CellID id; std::vector<T> data; // #if not defined(AKANTU_NDEBUG) // std::vector< Vector<Real> > positions; // #endif }; private: typedef std::map<CellID, Cell> cells_container; public: const Cell & getCell(const CellID & cell_id) const { typename cells_container::const_iterator it = cells.find(cell_id); if(it != cells.end()) return it->second; else return empty_cell; } typename Cell::iterator beginCell(const CellID & cell_id) { typename cells_container::iterator it = cells.find(cell_id); if(it != cells.end()) return it->second.begin(); else return empty_cell.begin(); } typename Cell::iterator endCell(const CellID & cell_id) { typename cells_container::iterator it = cells.find(cell_id); if(it != cells.end()) return it->second.end(); else return empty_cell.end(); } typename Cell::const_iterator beginCell(const CellID & cell_id) const { typename cells_container::const_iterator it = cells.find(cell_id); if(it != cells.end()) return it->second.begin(); else return empty_cell.begin(); } typename Cell::const_iterator endCell(const CellID & cell_id) const { typename cells_container::const_iterator it = cells.find(cell_id); if(it != cells.end()) return it->second.end(); else return empty_cell.end(); } class neighbor_cells_iterator : private std::iterator<std::forward_iterator_tag, UInt> { public: neighbor_cells_iterator(const CellID & cell_id, bool end) : cell_id(cell_id), position(cell_id.ids.size(), end ? 1 : -1) { this->updateIt(); if(end) this->it++; } neighbor_cells_iterator& operator++() { UInt i = 0; for (; i < position.size() && position(i) == 1; ++i); if(i == position.size()) ++it; else { for (UInt j = 0; j < i; ++j) position(j) = -1; position(i)++; updateIt(); } return *this; } neighbor_cells_iterator operator++(int) { neighbor_cells_iterator tmp(*this); operator++(); return tmp; }; bool operator==(const neighbor_cells_iterator& rhs) const { return cell_id == rhs.cell_id && it == rhs.it; }; bool operator!=(const neighbor_cells_iterator& rhs) const { return ! operator==(rhs); }; CellID operator*() const { CellID cur_cell_id(cell_id); cur_cell_id.ids += position; return cur_cell_id; }; private: void updateIt() { it = 0; for (UInt i = 0; i < position.size(); ++i) it = it * 3 + (position(i) + 1); } private: /// central cell id const CellID & cell_id; // number representing the current neighbor in base 3; UInt it; Vector<Int> position; }; class cells_iterator : private std::iterator<std::forward_iterator_tag, CellID> { public: cells_iterator(typename std::map<CellID, Cell>::const_iterator it) : it(it) { } cells_iterator & operator++() { this->it++; return *this; } cells_iterator operator++(int) {cells_iterator tmp(*this); operator++(); return tmp; }; bool operator==(const cells_iterator& rhs) const { return it == rhs.it; }; bool operator!=(const cells_iterator& rhs) const { return ! operator==(rhs); }; CellID operator*() const { CellID cur_cell_id(this->it->first); return cur_cell_id; }; private: /// map iterator typename std::map<CellID, Cell>::const_iterator it; }; public: template<class vector_type> Cell & insert(const T & d, const vector_type & position) { CellID cell_id = getCellID(position); typename cells_container::iterator it = cells.find(cell_id); if(it == cells.end()) { Cell cell(cell_id); // #if defined(AKANTU_NDEBUG) Cell & tmp = (cells[cell_id] = cell).add(d); // #else // Cell & tmp = (cells[cell_id] = cell).add(d, position); // #endif for (UInt i = 0; i < dimension; ++i) { Real posl = center(i) + cell_id.getID(i) * spacing(i); Real posu = posl + spacing(i); if(posl < lower(i)) lower(i) = posl; if(posu > upper(i)) upper(i) = posu; } return tmp; } else { // #if defined(AKANTU_NDEBUG) return it->second.add(d); // #else // return it->second.add(d, position); // #endif } } inline neighbor_cells_iterator beginNeighborCells(const CellID & cell_id) const { return neighbor_cells_iterator(cell_id, false); } inline neighbor_cells_iterator endNeighborCells(const CellID & cell_id) const { return neighbor_cells_iterator(cell_id, true); } inline cells_iterator beginCells() const { typename std::map<CellID, Cell>::const_iterator begin = this->cells.begin(); return cells_iterator(begin); } inline cells_iterator endCells() const { typename std::map<CellID, Cell>::const_iterator end = this->cells.end(); return cells_iterator(end); } template<class vector_type> CellID getCellID(const vector_type & position) const { CellID cell_id(dimension); for (UInt i = 0; i < dimension; ++i) { cell_id.setID(i, getCellID(position(i), i)); } return cell_id; } void printself(std::ostream & stream, int indent = 0) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); std::streamsize prec = stream.precision(); std::ios_base::fmtflags ff = stream.flags(); stream.setf (std::ios_base::showbase); stream.precision(5); stream << space << "SpatialGrid<" << debug::demangle(typeid(T).name()) << "> [" << std::endl; stream << space << " + dimension : " << this->dimension << std::endl; stream << space << " + lower bounds : {"; for (UInt i = 0; i < lower.size(); ++i) { if(i != 0) stream << ", "; stream << lower(i); }; stream << "}" << std::endl; stream << space << " + upper bounds : {"; for (UInt i = 0; i < upper.size(); ++i) { if(i != 0) stream << ", "; stream << upper(i); }; stream << "}" << std::endl; stream << space << " + spacing : {"; for (UInt i = 0; i < spacing.size(); ++i) { if(i != 0) stream << ", "; stream << spacing(i); }; stream << "}" << std::endl; stream << space << " + center : {"; for (UInt i = 0; i < center.size(); ++i) { if(i != 0) stream << ", "; stream << center(i); }; stream << "}" << std::endl; stream << space << " + nb_cells : " << this->cells.size() << "/"; Vector<Real> dist(this->dimension); dist = upper; dist -= lower; for (UInt i = 0; i < this->dimension; ++i) { dist(i) /= spacing(i); } UInt nb_cells = std::ceil(dist(0)); for (UInt i = 1; i < this->dimension; ++i) { nb_cells *= std::ceil(dist(i)); } stream << nb_cells << std::endl; stream << space << "]" << std::endl; stream.precision(prec); stream.flags(ff); } void saveAsMesh(Mesh & mesh) const; private: /* -------------------------------------------------------------------------- */ inline UInt getCellID(Real position, UInt direction) const { AKANTU_DEBUG_ASSERT(direction < center.size(), "The direction asked (" << direction << ") is out of range " << center.size()); Real dist_center = position - center(direction); Int id = std::floor(dist_center / spacing(direction)); //if(dist_center < 0) id--; return id; } friend class GridSynchronizer; public: AKANTU_GET_MACRO(LowerBounds, lower, const Vector<Real> &); AKANTU_GET_MACRO(UpperBounds, upper, const Vector<Real> &); AKANTU_GET_MACRO(Spacing, spacing, const Vector<Real> &); protected: UInt dimension; cells_container cells; Vector<Real> spacing; Vector<Real> center; Vector<Real> lower; Vector<Real> upper; Cell empty_cell; }; /// standard output stream operator template<typename T> inline std::ostream & operator <<(std::ostream & stream, const SpatialGrid<T> & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #include "mesh.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<typename T> void SpatialGrid<T>::saveAsMesh(Mesh & mesh) const { Array<Real> & nodes = const_cast<Array<Real> &>(mesh.getNodes()); ElementType type; switch(dimension) { case 1: type = _segment_2; break; case 2: type = _quadrangle_4; break; case 3: type = _hexahedron_8; break; } mesh.addConnectivityType(type); Array<UInt> & connectivity = const_cast<Array<UInt> &>(mesh.getConnectivity(type)); Array<UInt> & uint_data = *mesh.getDataPointer<UInt>("tag_1", type); typename cells_container::const_iterator it = cells.begin(); typename cells_container::const_iterator end = cells.end(); Vector<Real> pos(dimension); UInt global_id = 0; for (;it != end; ++it, ++global_id) { UInt cur_node = nodes.getSize(); UInt cur_elem = connectivity.getSize(); const CellID & cell_id = it->first; for (UInt i = 0; i < dimension; ++i) pos(i) = center(i) + cell_id.getID(i) * spacing(i); nodes.push_back(pos); for (UInt i = 0; i < dimension; ++i) pos(i) += spacing(i); nodes.push_back(pos); connectivity.push_back(cur_node); switch(dimension) { case 1: connectivity(cur_elem, 1) = cur_node + 1; break; case 2: pos(0) -= spacing(0); nodes.push_back(pos); pos(0) += spacing(0); pos(1) -= spacing(1); nodes.push_back(pos); connectivity(cur_elem, 1) = cur_node + 3; connectivity(cur_elem, 2) = cur_node + 1; connectivity(cur_elem, 3) = cur_node + 2; break; case 3: pos(1) -= spacing(1); pos(2) -= spacing(2); nodes.push_back(pos); pos(1) += spacing(1); nodes.push_back(pos); pos(0) -= spacing(0); nodes.push_back(pos); pos(1) -= spacing(1); pos(2) += spacing(2); nodes.push_back(pos); pos(0) += spacing(0); nodes.push_back(pos); pos(0) -= spacing(0); pos(1) += spacing(1); nodes.push_back(pos); connectivity(cur_elem, 1) = cur_node + 2; connectivity(cur_elem, 2) = cur_node + 3; connectivity(cur_elem, 3) = cur_node + 4; connectivity(cur_elem, 4) = cur_node + 5; connectivity(cur_elem, 5) = cur_node + 6; connectivity(cur_elem, 6) = cur_node + 1; connectivity(cur_elem, 7) = cur_node + 7; break; } uint_data.push_back(global_id); } // #if not defined(AKANTU_NDEBUG) // mesh.addConnectivityType(_point_1); // Array<UInt> & connectivity_pos = const_cast<Array<UInt> &>(mesh.getConnectivity(_point_1)); // Array<UInt> & uint_data_pos = *mesh.getDataPointer<UInt>( "tag_1", _point_1); // Array<UInt> & uint_data_pos_ghost = *mesh.getDataPointer<UInt>("tag_0", _point_1); // it = cells.begin(); // global_id = 0; // for (;it != end; ++it, ++global_id) { // typename Cell::position_iterator cell_it = it->second.begin_pos(); // typename Cell::const_iterator cell_it_cont = it->second.begin(); // typename Cell::position_iterator cell_end = it->second.end_pos(); // for (;cell_it != cell_end; ++cell_it, ++cell_it_cont) { // nodes.push_back(*cell_it); // connectivity_pos.push_back(nodes.getSize()-1); // uint_data_pos.push_back(global_id); // uint_data_pos_ghost.push_back(cell_it_cont->ghost_type==_ghost); // } // } // #endif } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_AKA_GRID_DYNAMIC_HH__ */ diff --git a/src/common/aka_math.cc b/src/common/aka_math.cc index 3129d10ca..ae03ed59a 100644 --- a/src/common/aka_math.cc +++ b/src/common/aka_math.cc @@ -1,251 +1,251 @@ /** * @file aka_math.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @author Peter Spijker <peter.spijker@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Aug 04 2010 * @date last modification: Fri May 15 2015 * * @brief Implementation of the math toolbox * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_math.hh" #include "aka_array.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ void Math::matrix_vector(UInt m, UInt n, const Array<Real> & A, const Array<Real> & x, Array<Real> & y, Real alpha) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(A.getSize() == x.getSize(), "The vector A(" << A.getID() << ") and the vector x(" << x.getID() << ") must have the same size"); AKANTU_DEBUG_ASSERT(A.getNbComponent() == m * n, "The vector A(" << A.getID() << ") has the good number of component."); AKANTU_DEBUG_ASSERT( x.getNbComponent() == n, "The vector x(" << x.getID() << ") do not the good number of component."); AKANTU_DEBUG_ASSERT( y.getNbComponent() == n, "The vector y(" << y.getID() << ") do not the good number of component."); UInt nb_element = A.getSize(); UInt offset_A = A.getNbComponent(); UInt offset_x = x.getNbComponent(); y.resize(nb_element); Real * A_val = A.storage(); Real * x_val = x.storage(); Real * y_val = y.storage(); for (UInt el = 0; el < nb_element; ++el) { matrix_vector(m, n, A_val, x_val, y_val, alpha); A_val += offset_A; x_val += offset_x; y_val += offset_x; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Math::matrix_matrix(UInt m, UInt n, UInt k, const Array<Real> & A, const Array<Real> & B, Array<Real> & C, Real alpha) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(A.getSize() == B.getSize(), "The vector A(" << A.getID() << ") and the vector B(" << B.getID() << ") must have the same size"); AKANTU_DEBUG_ASSERT(A.getNbComponent() == m * k, "The vector A(" << A.getID() << ") has the good number of component."); AKANTU_DEBUG_ASSERT( B.getNbComponent() == k * n, "The vector B(" << B.getID() << ") do not the good number of component."); AKANTU_DEBUG_ASSERT( C.getNbComponent() == m * n, "The vector C(" << C.getID() << ") do not the good number of component."); UInt nb_element = A.getSize(); UInt offset_A = A.getNbComponent(); UInt offset_B = B.getNbComponent(); UInt offset_C = C.getNbComponent(); C.resize(nb_element); Real * A_val = A.storage(); Real * B_val = B.storage(); Real * C_val = C.storage(); for (UInt el = 0; el < nb_element; ++el) { matrix_matrix(m, n, k, A_val, B_val, C_val, alpha); A_val += offset_A; B_val += offset_B; C_val += offset_C; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Math::matrix_matrixt(UInt m, UInt n, UInt k, const Array<Real> & A, const Array<Real> & B, Array<Real> & C, Real alpha) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(A.getSize() == B.getSize(), "The vector A(" << A.getID() << ") and the vector B(" << B.getID() << ") must have the same size"); AKANTU_DEBUG_ASSERT(A.getNbComponent() == m * k, "The vector A(" << A.getID() << ") has the good number of component."); AKANTU_DEBUG_ASSERT( B.getNbComponent() == k * n, "The vector B(" << B.getID() << ") do not the good number of component."); AKANTU_DEBUG_ASSERT( C.getNbComponent() == m * n, "The vector C(" << C.getID() << ") do not the good number of component."); UInt nb_element = A.getSize(); UInt offset_A = A.getNbComponent(); UInt offset_B = B.getNbComponent(); UInt offset_C = C.getNbComponent(); C.resize(nb_element); Real * A_val = A.storage(); Real * B_val = B.storage(); Real * C_val = C.storage(); for (UInt el = 0; el < nb_element; ++el) { matrix_matrixt(m, n, k, A_val, B_val, C_val, alpha); A_val += offset_A; B_val += offset_B; C_val += offset_C; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Math::compute_tangents(const Array<Real> & normals, Array<Real> & tangents) { AKANTU_DEBUG_IN(); UInt spatial_dimension = normals.getNbComponent(); UInt tangent_components = spatial_dimension * (spatial_dimension - 1); AKANTU_DEBUG_ASSERT( tangent_components == tangents.getNbComponent(), "Cannot compute the tangents, the storage array for tangents" << " does not have the good amount of components."); UInt nb_normals = normals.getSize(); tangents.resize(nb_normals); Real * normal_it = normals.storage(); Real * tangent_it = tangents.storage(); /// compute first tangent for (UInt q = 0; q < nb_normals; ++q) { /// if normal is orthogonal to xy plane, arbitrarly define tangent if (Math::are_float_equal(Math::norm2(normal_it), 0)) tangent_it[0] = 1; else Math::normal2(normal_it, tangent_it); normal_it += spatial_dimension; tangent_it += tangent_components; } /// compute second tangent (3D case) if (spatial_dimension == 3) { normal_it = normals.storage(); tangent_it = tangents.storage(); for (UInt q = 0; q < nb_normals; ++q) { Math::normal3(normal_it, tangent_it, tangent_it + spatial_dimension); normal_it += spatial_dimension; tangent_it += tangent_components; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real Math::reduce(Array<Real> & array) { UInt nb_values = array.getSize(); if (nb_values == 0) return 0.; UInt nb_values_to_sum = nb_values >> 1; std::sort(array.begin(), array.end()); // as long as the half is not empty while (nb_values_to_sum) { UInt remaining = (nb_values - 2 * nb_values_to_sum); if (remaining) array(nb_values - 2) += array(nb_values - 1); // sum to consecutive values and store the sum in the first half for (UInt i = 0; i < nb_values_to_sum; ++i) { array(i) = array(2 * i) + array(2 * i + 1); } nb_values = nb_values_to_sum; nb_values_to_sum >>= 1; } return array(0); } -__END_AKANTU__ +} // akantu diff --git a/src/common/aka_math.hh b/src/common/aka_math.hh index 44389f462..18409e62b 100644 --- a/src/common/aka_math.hh +++ b/src/common/aka_math.hh @@ -1,291 +1,291 @@ /** * @file aka_math.hh * * @author Ramin Aghababaei <ramin.aghababaei@epfl.ch> * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @author Peter Spijker <peter.spijker@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Aug 04 2010 * @date last modification: Fri May 15 2015 * * @brief mathematical operations * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_MATH_H__ #define __AKANTU_AKA_MATH_H__ /* -------------------------------------------------------------------------- */ #include <utility> #include "aka_common.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <typename T, bool is_scal> class Array; class Math { /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Matrix algebra */ /* ------------------------------------------------------------------------ */ /// @f$ y = A*x @f$ static void matrix_vector(UInt m, UInt n, const Array<Real, true> & A, const Array<Real, true> & x, Array<Real, true> & y, Real alpha = 1.); /// @f$ y = A*x @f$ static inline void matrix_vector(UInt m, UInt n, Real * A, Real * x, Real * y, Real alpha = 1.); /// @f$ y = A^t*x @f$ static inline void matrixt_vector(UInt m, UInt n, Real * A, Real * x, Real * y, Real alpha = 1.); /// @f$ C = A*B @f$ static void matrix_matrix(UInt m, UInt n, UInt k, const Array<Real, true> & A, const Array<Real, true> & B, Array<Real, true> & C, Real alpha = 1.); /// @f$ C = A*B^t @f$ static void matrix_matrixt(UInt m, UInt n, UInt k, const Array<Real, true> & A, const Array<Real, true> & B, Array<Real, true> & C, Real alpha = 1.); /// @f$ C = A*B @f$ static inline void matrix_matrix(UInt m, UInt n, UInt k, Real * A, Real * B, Real * C, Real alpha = 1.); /// @f$ C = A^t*B @f$ static inline void matrixt_matrix(UInt m, UInt n, UInt k, Real * A, Real * B, Real * C, Real alpha = 1.); /// @f$ C = A*B^t @f$ static inline void matrix_matrixt(UInt m, UInt n, UInt k, Real * A, Real * B, Real * C, Real alpha = 1.); /// @f$ C = A^t*B^t @f$ static inline void matrixt_matrixt(UInt m, UInt n, UInt k, Real * A, Real * B, Real * C, Real alpha = 1.); template <bool tr_A, bool tr_B> static inline void matMul(UInt m, UInt n, UInt k, Real alpha, Real * A, Real * B, Real beta, Real * C); template <bool tr_A> static inline void matVectMul(UInt m, UInt n, Real alpha, Real * A, Real * x, Real beta, Real * y); static inline void aXplusY(UInt n, Real alpha, Real * x, Real * y); static inline void matrix33_eigenvalues(Real * A, Real * Adiag); static inline void matrix22_eigenvalues(Real * A, Real * Adiag); template <UInt dim> static inline void eigenvalues(Real * A, Real * d); /// solve @f$ A x = \Lambda x @f$ and return d and V such as @f$ A V[i:] = /// d[i] V[i:]@f$ template <typename T> static void matrixEig(UInt n, T * A, T * d, T * V = nullptr); /// determinent of a 2x2 matrix static inline Real det2(const Real * mat); /// determinent of a 3x3 matrix static inline Real det3(const Real * mat); /// determinent of a nxn matrix template <UInt n> static inline Real det(const Real * mat); /// determinent of a nxn matrix template <typename T> static inline T det(UInt n, const T * mat); /// inverse a nxn matrix template <UInt n> static inline void inv(const Real * mat, Real * inv); /// inverse a nxn matrix template <typename T> static inline void inv(UInt n, const T * mat, T * inv); /// inverse a 3x3 matrix static inline void inv3(const Real * mat, Real * inv); /// inverse a 2x2 matrix static inline void inv2(const Real * mat, Real * inv); /// solve A x = b using a LU factorization template <typename T> static inline void solve(UInt n, const T * A, T * x, const T * b); /// return the double dot product between 2 tensors in 2d static inline Real matrixDoubleDot22(Real * A, Real * B); /// return the double dot product between 2 tensors in 3d static inline Real matrixDoubleDot33(Real * A, Real * B); /// extension of the double dot product to two 2nd order tensor in dimension n static inline Real matrixDoubleDot(UInt n, Real * A, Real * B); /* ------------------------------------------------------------------------ */ /* Array algebra */ /* ------------------------------------------------------------------------ */ /// vector cross product static inline void vectorProduct3(const Real * v1, const Real * v2, Real * res); /// normalize a vector static inline void normalize2(Real * v); /// normalize a vector static inline void normalize3(Real * v); /// return norm of a 2-vector static inline Real norm2(const Real * v); /// return norm of a 3-vector static inline Real norm3(const Real * v); /// return norm of a vector static inline Real norm(UInt n, const Real * v); /// return the dot product between 2 vectors in 2d static inline Real vectorDot2(const Real * v1, const Real * v2); /// return the dot product between 2 vectors in 3d static inline Real vectorDot3(const Real * v1, const Real * v2); /// return the dot product between 2 vectors static inline Real vectorDot(Real * v1, Real * v2, UInt n); /* ------------------------------------------------------------------------ */ /* Geometry */ /* ------------------------------------------------------------------------ */ /// compute normal a normal to a vector static inline void normal2(const Real * v1, Real * res); /// compute normal a normal to a vector static inline void normal3(const Real * v1, const Real * v2, Real * res); /// compute the tangents to an array of normal vectors static void compute_tangents(const Array<Real> & normals, Array<Real> & tangents); /// distance in 2D between x and y static inline Real distance_2d(const Real * x, const Real * y); /// distance in 3D between x and y static inline Real distance_3d(const Real * x, const Real * y); /// radius of the in-circle of a triangle static inline Real triangle_inradius(const Real * coord1, const Real * coord2, const Real * coord3); /// radius of the in-circle of a tetrahedron static inline Real tetrahedron_inradius(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4); /// volume of a tetrahedron static inline Real tetrahedron_volume(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4); /// compute the barycenter of n points static inline void barycenter(const Real * coord, UInt nb_points, UInt spatial_dimension, Real * barycenter); /// vector between x and y static inline void vector_2d(const Real * x, const Real * y, Real * vec); /// vector pointing from x to y in 3 spatial dimension static inline void vector_3d(const Real * x, const Real * y, Real * vec); /// test if two scalar are equal within a given tolerance static inline bool are_float_equal(Real x, Real y); /// test if two vectors are equal within a given tolerance static inline bool are_vector_equal(UInt n, Real * x, Real * y); #ifdef isnan #error \ "You probably included <math.h> which is incompatible with aka_math please use\ <cmath> or add a \"#undef isnan\" before akantu includes" #endif /// test if a real is a NaN static inline bool isnan(Real x); /// test if the line x and y intersects each other static inline bool intersects(Real x_min, Real x_max, Real y_min, Real y_max); /// test if a is in the range [x_min, x_max] static inline bool is_in_range(Real a, Real x_min, Real x_max); static inline Real getTolerance() { return tolerance; }; static inline void setTolerance(Real tol) { tolerance = tol; }; template <UInt p, typename T> static inline T pow(T x); /// reduce all the values of an array, the summation is done in place and the /// array is modified static Real reduce(Array<Real> & array); class NewtonRaphson { public: NewtonRaphson(Real tolerance, Real max_iteration) : tolerance(tolerance), max_iteration(max_iteration) {} template <class Functor> Real solve(const Functor & funct, Real x_0); private: Real tolerance; Real max_iteration; }; struct NewtonRaphsonFunctor { NewtonRaphsonFunctor(std::string name) : name(std::move(name)) {} virtual Real f(Real x) const = 0; virtual Real f_prime(Real x) const = 0; std::string name; }; private: /// tolerance for functions that need one static Real tolerance; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "aka_math_tmpl.hh" -__END_AKANTU__ +} // akantu #endif /* __AKANTU_AKA_MATH_H__ */ diff --git a/src/common/aka_math_tmpl.hh b/src/common/aka_math_tmpl.hh index 18f64791e..ebf148bfb 100644 --- a/src/common/aka_math_tmpl.hh +++ b/src/common/aka_math_tmpl.hh @@ -1,786 +1,786 @@ /** * @file aka_math_tmpl.hh * * @author Ramin Aghababaei <ramin.aghababaei@epfl.ch> * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Alejandro M. Aragón <alejandro.aragon@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Mathilde Radiguet <mathilde.radiguet@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @author Peter Spijker <peter.spijker@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Aug 04 2010 * @date last modification: Wed Oct 21 2015 * * @brief Implementation of the inline functions of the math toolkit * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ -__END_AKANTU__ +} // akantu #include <cmath> #include <cstring> #include <typeinfo> #include "aka_blas_lapack.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ inline void Math::matrix_vector(UInt im, UInt in, Real * A, Real * x, Real * y, Real alpha) { #ifdef AKANTU_USE_BLAS /// y = alpha*op(A)*x + beta*y char tran_A = 'N'; int incx = 1; int incy = 1; double beta = 0.; int m = im; int n = in; aka_gemv(&tran_A, &m, &n, &alpha, A, &m, x, &incx, &beta, y, &incy); #else memset(y, 0, im * sizeof(Real)); for (UInt i = 0; i < im; ++i) { for (UInt j = 0; j < in; ++j) { y[i] += A[i + j * im] * x[j]; } y[i] *= alpha; } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrixt_vector(UInt im, UInt in, Real * A, Real * x, Real * y, Real alpha) { #ifdef AKANTU_USE_BLAS /// y = alpha*op(A)*x + beta*y char tran_A = 'T'; int incx = 1; int incy = 1; double beta = 0.; int m = im; int n = in; aka_gemv(&tran_A, &m, &n, &alpha, A, &m, x, &incx, &beta, y, &incy); #else memset(y, 0, in * sizeof(Real)); for (UInt i = 0; i < im; ++i) { for (UInt j = 0; j < in; ++j) { y[j] += A[j * im + i] * x[i]; } y[i] *= alpha; } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrix_matrix(UInt im, UInt in, UInt ik, Real * A, Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C char trans_a = 'N'; char trans_b = 'N'; double beta = 0.; int m = im, n = in, k = ik; aka_gemm(&trans_a, &trans_b, &m, &n, &k, &alpha, A, &m, B, &k, &beta, C, &m); #else memset(C, 0, im * in * sizeof(Real)); for (UInt j = 0; j < in; ++j) { UInt _jb = j * ik; UInt _jc = j * im; for (UInt i = 0; i < im; ++i) { for (UInt l = 0; l < ik; ++l) { UInt _la = l * im; C[i + _jc] += A[i + _la] * B[l + _jb]; } C[i + _jc] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrixt_matrix(UInt im, UInt in, UInt ik, Real * A, Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C char trans_a = 'T'; char trans_b = 'N'; double beta = 0.; int m = im, n = in, k = ik; aka_gemm(&trans_a, &trans_b, &m, &n, &k, &alpha, A, &k, B, &k, &beta, C, &m); #else memset(C, 0, im * in * sizeof(Real)); for (UInt j = 0; j < in; ++j) { UInt _jc = j * im; UInt _jb = j * ik; for (UInt i = 0; i < im; ++i) { UInt _ia = i * ik; for (UInt l = 0; l < ik; ++l) { C[i + _jc] += A[l + _ia] * B[l + _jb]; } C[i + _jc] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrix_matrixt(UInt im, UInt in, UInt ik, Real * A, Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C char trans_a = 'N'; char trans_b = 'T'; double beta = 0.; int m = im, n = in, k = ik; aka_gemm(&trans_a, &trans_b, &m, &n, &k, &alpha, A, &m, B, &n, &beta, C, &m); #else memset(C, 0, im * in * sizeof(Real)); for (UInt j = 0; j < in; ++j) { UInt _jc = j * im; for (UInt i = 0; i < im; ++i) { for (UInt l = 0; l < ik; ++l) { UInt _la = l * im; UInt _lb = l * in; C[i + _jc] += A[i + _la] * B[j + _lb]; } C[i + _jc] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrixt_matrixt(UInt im, UInt in, UInt ik, Real * A, Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C char trans_a = 'T'; char trans_b = 'T'; double beta = 0.; int m = im, n = in, k = ik; aka_gemm(&trans_a, &trans_b, &m, &n, &k, &alpha, A, &k, B, &n, &beta, C, &m); #else memset(C, 0, im * in * sizeof(Real)); for (UInt j = 0; j < in; ++j) { UInt _jc = j * im; for (UInt i = 0; i < im; ++i) { UInt _ia = i * ik; for (UInt l = 0; l < ik; ++l) { UInt _lb = l * in; C[i + _jc] += A[l + _ia] * B[j + _lb]; } C[i + _jc] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::aXplusY(UInt n, Real alpha, Real * x, Real * y) { #ifdef AKANTU_USE_BLAS /// y := alpha x + y int incx = 1, incy = 1; aka_axpy(&n, &alpha, x, &incx, y, &incy); #else for (UInt i = 0; i < n; ++i) *(y++) += alpha * *(x++); #endif } /* -------------------------------------------------------------------------- */ inline Real Math::vectorDot(Real * v1, Real * v2, UInt in) { #ifdef AKANTU_USE_BLAS /// d := v1 . v2 int incx = 1, incy = 1, n = in; Real d = aka_dot(&n, v1, &incx, v2, &incy); #else Real d = 0; for (UInt i = 0; i < in; ++i) { d += v1[i] * v2[i]; } #endif return d; } /* -------------------------------------------------------------------------- */ template <bool tr_A, bool tr_B> inline void Math::matMul(UInt m, UInt n, UInt k, Real alpha, Real * A, Real * B, __attribute__((unused)) Real beta, Real * C) { 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); } } /* -------------------------------------------------------------------------- */ template <bool tr_A> inline void Math::matVectMul(UInt m, UInt n, Real alpha, Real * A, Real * x, __attribute__((unused)) Real beta, Real * y) { if (tr_A) { matrixt_vector(m, n, A, x, y, alpha); } else { matrix_vector(m, n, A, x, y, alpha); } } /* -------------------------------------------------------------------------- */ template <typename T> inline void Math::matrixEig(UInt n, T * A, T * d, T * V) { // Matrix A is row major, so the lapack function in fortran will process // A^t. Asking for the left eigenvectors of A^t will give the transposed right // eigenvectors of A so in the C++ code the right eigenvectors. char jobvl; if (V != nullptr) jobvl = 'V'; // compute left eigenvectors else jobvl = 'N'; // compute left eigenvectors char jobvr('N'); // compute right eigenvectors auto * di = new T[n]; // imaginary part of the eigenvalues int info; int N = n; T wkopt; int lwork = -1; // query and allocate the optimal workspace aka_geev<T>(&jobvl, &jobvr, &N, A, &N, d, di, V, &N, nullptr, &N, &wkopt, &lwork, &info); lwork = int(wkopt); auto * work = new T[lwork]; // solve the eigenproblem aka_geev<T>(&jobvl, &jobvr, &N, A, &N, d, di, V, &N, nullptr, &N, work, &lwork, &info); AKANTU_DEBUG_ASSERT( info == 0, "Problem computing eigenvalues/vectors. DGEEV exited with the value " << info); delete[] work; delete[] di; // I hope for you that there was no complex eigenvalues !!! } /* -------------------------------------------------------------------------- */ inline void Math::matrix22_eigenvalues(Real * A, Real * Adiag) { /// d = determinant of Matrix A Real d = det2(A); /// b = trace of Matrix A Real b = A[0] + A[3]; Real c = sqrt(b * b - 4 * d); Adiag[0] = .5 * (b + c); Adiag[1] = .5 * (b - c); } /* -------------------------------------------------------------------------- */ inline void Math::matrix33_eigenvalues(Real * A, Real * Adiag) { matrixEig(3, A, Adiag); } /* -------------------------------------------------------------------------- */ template <UInt dim> inline void Math::eigenvalues(Real * A, Real * d) { if (dim == 1) { d[0] = A[0]; } else if (dim == 2) { matrix22_eigenvalues(A, d); } // else if(dim == 3) { matrix33_eigenvalues(A, d); } else matrixEig(dim, A, d); } /* -------------------------------------------------------------------------- */ 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]); } /* -------------------------------------------------------------------------- */ template <UInt n> inline Real Math::det(const Real * mat) { if (n == 1) return *mat; else if (n == 2) return det2(mat); else if (n == 3) return det3(mat); else return det(n, mat); } /* -------------------------------------------------------------------------- */ template <typename T> inline T Math::det(UInt n, const T * A) { int N = n; int info; auto * ipiv = new int[N + 1]; auto * LU = new T[N * N]; std::copy(A, A + N * N, LU); // LU factorization of A aka_getrf(&N, &N, LU, &N, ipiv, &info); if (info > 0) { AKANTU_DEBUG_ERROR("Singular matrix - cannot factorize it (info: " << info << " )"); } // det(A) = det(L) * det(U) = 1 * det(U) = product_i U_{ii} T det = 1.; for (int i = 0; i < N; ++i) det *= (2 * (ipiv[i] == i) - 1) * LU[i * n + i]; delete[] ipiv; delete[] LU; return det; } /* -------------------------------------------------------------------------- */ 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 Real Math::norm(UInt n, const Real * vec) { Real norm = 0.; for (UInt i = 0; i < n; ++i) { norm += vec[i] * vec[i]; } return sqrt(norm); } /* -------------------------------------------------------------------------- */ 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; } /* -------------------------------------------------------------------------- */ template <UInt n> inline void Math::inv(const Real * A, Real * Ainv) { if (n == 1) *Ainv = 1. / *A; else if (n == 2) inv2(A, Ainv); else if (n == 3) inv3(A, Ainv); else inv(n, A, Ainv); } /* -------------------------------------------------------------------------- */ template <typename T> inline void Math::inv(UInt n, const T * A, T * invA) { int N = n; int info; auto * ipiv = new int[N + 1]; int lwork = N * N; auto * work = new T[lwork]; std::copy(A, A + n * n, invA); aka_getrf(&N, &N, invA, &N, ipiv, &info); if (info > 0) { AKANTU_DEBUG_ERROR("Singular matrix - cannot factorize it (info: " << info << " )"); } aka_getri(&N, invA, &N, ipiv, work, &lwork, &info); if (info != 0) { AKANTU_DEBUG_ERROR("Cannot invert the matrix (info: " << info << " )"); } delete[] ipiv; delete[] work; } /* -------------------------------------------------------------------------- */ template <typename T> inline void Math::solve(UInt n, const T * A, T * x, const T * b) { int N = n; int info; auto * ipiv = new int[N]; auto * lu_A = new T[N * N]; std::copy(A, A + N * N, lu_A); aka_getrf(&N, &N, lu_A, &N, ipiv, &info); if (info > 0) { AKANTU_DEBUG_ERROR("Singular matrix - cannot factorize it (info: " << info << " )"); exit(EXIT_FAILURE); } char trans = 'N'; int nrhs = 1; std::copy(b, b + N, x); aka_getrs(&trans, &N, &nrhs, lu_A, &N, ipiv, x, &N, &info); if (info != 0) { AKANTU_DEBUG_ERROR("Cannot solve the system (info: " << info << " )"); exit(EXIT_FAILURE); } delete[] ipiv; delete[] lu_A; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ inline Real Math::matrixDoubleDot22(Real * A, Real * B) { Real d; d = A[0] * B[0] + A[1] * B[1] + A[2] * B[2] + A[3] * B[3]; return d; } /* -------------------------------------------------------------------------- */ inline Real Math::matrixDoubleDot33(Real * A, Real * B) { Real d; d = A[0] * B[0] + A[1] * B[1] + A[2] * B[2] + A[3] * B[3] + A[4] * B[4] + A[5] * B[5] + A[6] * B[6] + A[7] * B[7] + A[8] * B[8]; return d; } /* -------------------------------------------------------------------------- */ inline Real Math::matrixDoubleDot(UInt n, Real * A, Real * B) { Real d = 0.; for (UInt i = 0; i < n; ++i) { for (UInt j = 0; j < n; ++j) { d += A[i * n + j] * B[i * n + j]; } } return d; } /* -------------------------------------------------------------------------- */ 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 + l14) * 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]; } /* -------------------------------------------------------------------------- */ /// Combined absolute and relative tolerance test proposed in /// Real-time collision detection by C. Ericson (2004) inline bool Math::are_float_equal(const Real x, const Real y) { Real abs_max = std::max(std::abs(x), std::abs(y)); abs_max = std::max(abs_max, Real(1.)); return std::abs(x - y) <= (tolerance * abs_max); } /* -------------------------------------------------------------------------- */ inline bool Math::isnan(Real x) { #if defined(__INTEL_COMPILER) #pragma warning(push) #pragma warning(disable : 1572) #endif // defined(__INTEL_COMPILER) // x = x return false means x = quiet_NaN return !(x == x); #if defined(__INTEL_COMPILER) #pragma warning(pop) #endif // defined(__INTEL_COMPILER) } /* -------------------------------------------------------------------------- */ 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; } /* -------------------------------------------------------------------------- */ inline bool Math::intersects(Real x_min, Real x_max, Real y_min, Real y_max) { return !((x_max <= y_min) || (x_min >= y_max)); } /* -------------------------------------------------------------------------- */ inline bool Math::is_in_range(Real a, Real x_min, Real x_max) { return ((a >= x_min) && (a <= x_max)); } /* -------------------------------------------------------------------------- */ template <UInt p, typename T> inline T Math::pow(T x) { return (pow<p - 1, T>(x) * x); } template <> inline UInt Math::pow<0, UInt>(__attribute__((unused)) UInt x) { return (1); } template <> inline Real Math::pow<0, Real>(__attribute__((unused)) Real x) { return (1.); } /* -------------------------------------------------------------------------- */ template <class Functor> Real Math::NewtonRaphson::solve(const Functor & funct, Real x_0) { Real x = x_0; Real f_x = funct.f(x); UInt iter = 0; while (std::abs(f_x) > this->tolerance && iter < this->max_iteration) { x -= f_x / funct.f_prime(x); f_x = funct.f(x); iter++; } AKANTU_DEBUG_ASSERT(iter < this->max_iteration, "Newton Raphson (" << funct.name << ") solve did not converge in " << this->max_iteration << " iterations (tolerance: " << this->tolerance << ")"); return x; } diff --git a/src/common/aka_memory.cc b/src/common/aka_memory.cc index 7db2e7a1b..748167122 100644 --- a/src/common/aka_memory.cc +++ b/src/common/aka_memory.cc @@ -1,64 +1,64 @@ /** * @file aka_memory.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief static memory wrapper * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" #include "aka_static_memory.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ Memory::Memory(ID id, MemoryID memory_id) : static_memory(StaticMemory::getStaticMemory()), id(id), memory_id(memory_id) { } /* -------------------------------------------------------------------------- */ Memory::~Memory() { if(StaticMemory::isInstantiated()) { std::list<ID>::iterator it; for (it = handeld_vectors_id.begin(); it != handeld_vectors_id.end(); ++it) { AKANTU_DEBUG(dblAccessory, "Deleting the vector " << *it); static_memory.sfree(memory_id, *it); } static_memory.destroy(); } handeld_vectors_id.clear(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/common/aka_memory.hh b/src/common/aka_memory.hh index ede733233..04d942c02 100644 --- a/src/common/aka_memory.hh +++ b/src/common/aka_memory.hh @@ -1,115 +1,115 @@ /** * @file aka_memory.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief wrapper for the static_memory, all object which wants * to access the static_memory as to inherit from the class memory * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MEMORY_HH__ #define __AKANTU_MEMORY_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_static_memory.hh" #include "aka_array.hh" /* -------------------------------------------------------------------------- */ #include <list> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ protected: Memory(ID id, MemoryID memory_id = 0); virtual ~Memory(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ protected: /// malloc template <class T> inline Array<T> & alloc(const ID & name, UInt size, UInt nb_component); /// malloc template <class T> inline Array<T> & alloc(const ID & name, UInt size, UInt nb_component, const T & init_value); /* ------------------------------------------------------------------------ */ /// free an array inline void dealloc(ID name); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ protected: template <typename T> inline Array<T> & getArray(const ID & name); template <typename T> inline const Array<T> & getArray(const ID & name) const; public: AKANTU_GET_MACRO(MemoryID, memory_id, const MemoryID &); AKANTU_GET_MACRO(ID, id, const ID &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// the static memory instance StaticMemory & static_memory; /// list of allocated vectors id std::list<ID> handeld_vectors_id; protected: ID id; /// the id registred in the static memory MemoryID memory_id; }; /* -------------------------------------------------------------------------- */ /* Inline functions */ /* -------------------------------------------------------------------------- */ #if defined(AKANTU_INCLUDE_INLINE_IMPL) #include "aka_memory_inline_impl.cc" #endif -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MEMORY_HH__ */ diff --git a/src/common/aka_random_generator.hh b/src/common/aka_random_generator.hh index 8b756c20f..de6913d7a 100644 --- a/src/common/aka_random_generator.hh +++ b/src/common/aka_random_generator.hh @@ -1,376 +1,376 @@ /** * @file aka_random_generator.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Wed Nov 11 2015 * * @brief generic random generator * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" #include "aka_common.hh" #ifndef __AKANTU_AKA_RANDOM_GENERATOR_HH__ #define __AKANTU_AKA_RANDOM_GENERATOR_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* List of available distributions */ /* -------------------------------------------------------------------------- */ #define AKANTU_RANDOM_DISTRIBUTION_TYPES \ ((uniform, UniformDistribution))((weibull, WeibullDistribution)) #define AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX(elem) BOOST_PP_CAT(_rdt_, elem) #define AKANTU_RANDOM_DISTRIBUTION_PREFIX(s, data, elem) \ AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX(BOOST_PP_TUPLE_ELEM(2, 0, elem)) enum RandomDistributionType { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(AKANTU_RANDOM_DISTRIBUTION_PREFIX, _, AKANTU_RANDOM_DISTRIBUTION_TYPES)), _rdt_not_defined }; /* -------------------------------------------------------------------------- */ /* Distribution */ /* -------------------------------------------------------------------------- */ /// Empty base to be able to store a distribution template <typename T> class RandomDistributionBase { public: virtual ~RandomDistributionBase() {} virtual void printself(std::ostream & stream, int indent = 0) const = 0; }; /* -------------------------------------------------------------------------- */ /* Uniform distribution */ /* -------------------------------------------------------------------------- */ template <typename T> class UniformDistribution : public RandomDistributionBase<T> { public: UniformDistribution(T min = T(0.), T max = T(1.)) : min(min), max(max){}; /* ------------------------------------------------------------------------ */ template <template <class> class RandomGenerator> T operator()(RandomGenerator<T> & generator) { T x = generator() / (RandomGenerator<T>::max() - RandomGenerator<T>::min()); return (x * (max - min) + min); } virtual void setParams(std::string value) { std::stringstream sstr(value); sstr >> min; sstr >> max; } /// function to print the contain of the class virtual void printself(std::ostream & stream, __attribute__((unused)) int indent = 0) const { stream << "Uniform [ min=" << min << ", max=" << max << " ]"; }; /* ------------------------------------------------------------------------ */ private: T min; T max; }; /* -------------------------------------------------------------------------- */ /* Weibull distribution */ /* -------------------------------------------------------------------------- */ template <typename T> class WeibullDistribution : public RandomDistributionBase<T> { public: WeibullDistribution(T scale, T shape) : m(shape), lambda(scale){}; /* ------------------------------------------------------------------------ */ template <template <class> class RandomGenerator> T operator()(RandomGenerator<T> & generator) { T x = generator() / (RandomGenerator<T>::max() - RandomGenerator<T>::min()); T e = T(1) / m; return lambda * std::pow(-std::log(1. - x), e); } virtual void setParams(std::string value) { std::stringstream sstr(value); sstr >> m; sstr >> lambda; } /// function to print the contain of the class virtual void printself(std::ostream & stream, __attribute__((unused)) int indent = 0) const { stream << "Weibull [ shape=" << m << ", scale=" << lambda << "]"; } /* ------------------------------------------------------------------------ */ private: /// shape parameter or Weibull modulus T m; /// scale parameter T lambda; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* Generator */ /* -------------------------------------------------------------------------- */ #if not defined(_WIN32) template <typename T> class Rand48Generator { /* ------------------------------------------------------------------------ */ public: inline T operator()(); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ public: static void seed(long int s); static long int seed(); static constexpr T min(); static constexpr T max(); /* ------------------------------------------------------------------------ */ private: static long int _seed; }; /* -------------------------------------------------------------------------- */ template <typename T> inline T Rand48Generator<T>::operator()() { AKANTU_DEBUG_TO_IMPLEMENT(); } template <> inline double Rand48Generator<double>::operator()() { return drand48(); } template <typename T> void Rand48Generator<T>::printself(std::ostream & stream, __attribute__((unused)) int indent) const { stream << "Rand48Generator [seed=" << seed << "]"; } template <typename T> void Rand48Generator<T>::seed(long int s) { _seed = s; srand48(_seed); } template <typename T> long int Rand48Generator<T>::seed() { return _seed; } template <typename T> constexpr T Rand48Generator<T>::min() { return 0.; } template <typename T> constexpr T Rand48Generator<T>::max() { return 1.; } #endif /* -------------------------------------------------------------------------- */ template <typename T> class RandGenerator { /* ------------------------------------------------------------------------ */ public: inline T operator()() { return rand(); } /// function to print the contain of the class virtual void printself(std::ostream & stream, __attribute__((unused)) int indent = 0) const { stream << "RandGenerator [seed=" << _seed << "]"; } /* ------------------------------------------------------------------------ */ public: static void seed(long int s) { _seed = s; srand(_seed); } static long int seed() { return _seed; } static constexpr T min() { return 0.; } static constexpr T max() { return RAND_MAX; } /* ------------------------------------------------------------------------ */ private: static long int _seed; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #undef AKANTU_RANDOM_DISTRIBUTION_PREFIX #define AKANTU_RANDOM_DISTRIBUTION_TYPE_PRINT_CASE(r, data, elem) \ case AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX( \ BOOST_PP_TUPLE_ELEM(2, 0, elem)): { \ stream << BOOST_PP_STRINGIZE(AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX( \ BOOST_PP_TUPLE_ELEM(2, 0, elem))); \ break; \ } inline std::ostream & operator<<(std::ostream & stream, RandomDistributionType type) { switch (type) { BOOST_PP_SEQ_FOR_EACH(AKANTU_RANDOM_DISTRIBUTION_TYPE_PRINT_CASE, _, AKANTU_RANDOM_DISTRIBUTION_TYPES) default: stream << UInt(type) << " not a RandomDistributionType"; break; } return stream; } #undef AKANTU_RANDOM_DISTRIBUTION_TYPE_PRINT_CASE /* -------------------------------------------------------------------------- */ /* Some Helper */ /* -------------------------------------------------------------------------- */ template <typename T, template <typename> class Distribution> class RandomDistributionTypeHelper { enum { value = _rdt_not_defined }; }; /* -------------------------------------------------------------------------- */ #define AKANTU_RANDOM_DISTRIBUTION_TYPE_GET_TYPE(r, data, elem) \ template <typename T> \ struct RandomDistributionTypeHelper<T, BOOST_PP_TUPLE_ELEM(2, 1, elem)> { \ enum { \ value = AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX( \ BOOST_PP_TUPLE_ELEM(2, 0, elem)) \ }; \ }; BOOST_PP_SEQ_FOR_EACH(AKANTU_RANDOM_DISTRIBUTION_TYPE_GET_TYPE, _, AKANTU_RANDOM_DISTRIBUTION_TYPES) #undef AKANTU_RANDOM_DISTRIBUTION_TYPE_GET_TYPE /* -------------------------------------------------------------------------- */ /* RandomParameter */ /* -------------------------------------------------------------------------- */ template <typename T> class RandomParameter { public: explicit RandomParameter(T base_value) : base_value(base_value), type(_rdt_not_defined), distribution(NULL) {} template <template <typename> class Distribution> RandomParameter(T base_value, const Distribution<T> & distribution) : base_value(base_value), type((RandomDistributionType) RandomDistributionTypeHelper<T, Distribution>::value), distribution(new Distribution<T>(distribution)) {} #define AKANTU_RANDOM_DISTRIBUTION_TYPE_NEW(r, data, elem) \ else if (type == AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX( \ BOOST_PP_TUPLE_ELEM(2, 0, elem))) { \ typedef BOOST_PP_TUPLE_ELEM(2, 1, elem)<T> Dist; \ distribution = new Dist(*static_cast<Dist *>(other.distribution)); \ } RandomParameter(const RandomParameter & other) : base_value(other.base_value), type(other.type) { if (type == _rdt_not_defined) distribution = NULL; BOOST_PP_SEQ_FOR_EACH(AKANTU_RANDOM_DISTRIBUTION_TYPE_NEW, _, AKANTU_RANDOM_DISTRIBUTION_TYPES) } inline void setBaseValue(const T & value) { this->base_value = value; } inline T getBaseValue() const { return this->base_value; } RandomParameter & operator=(const RandomParameter & other) { if (this != &other) { base_value = other.base_value; type = other.type; delete distribution; if (type == _rdt_not_defined) distribution = NULL; BOOST_PP_SEQ_FOR_EACH(AKANTU_RANDOM_DISTRIBUTION_TYPE_NEW, _, AKANTU_RANDOM_DISTRIBUTION_TYPES) } return *this; } #undef AKANTU_RANDOM_DISTRIBUTION_TYPE_NEW /* ------------------------------------------------------------------------ */ #define AKANTU_RANDOM_DISTRIBUTION_TYPE_SET(r, data, elem) \ else if (type == AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX( \ BOOST_PP_TUPLE_ELEM(2, 0, elem))) { \ this->set<BOOST_PP_TUPLE_ELEM(2, 1, elem), Generator>(it, end); \ } template <template <typename> class Generator, class iterator> void setValues(iterator it, iterator end) { if (type == _rdt_not_defined) { for (; it != end; ++it) *it = this->base_value; } BOOST_PP_SEQ_FOR_EACH(AKANTU_RANDOM_DISTRIBUTION_TYPE_SET, _, AKANTU_RANDOM_DISTRIBUTION_TYPES) } #undef AKANTU_RANDOM_DISTRIBUTION_TYPE_SET virtual void printself(std::ostream & stream, __attribute__((unused)) int indent = 0) const { stream << base_value; if (type != _rdt_not_defined) stream << " " << *distribution; } private: template <template <typename> class Distribution, template <typename> class Generator, class iterator> void set(iterator it, iterator end) { typedef Distribution<T> Dist; Dist & dist = *(static_cast<Dist *>(this->distribution)); Generator<T> gen; for (; it != end; ++it) *it = this->base_value + dist(gen); } private: /// Value with no random variations T base_value; /// Random distribution type RandomDistributionType type; /// Random distribution to use RandomDistributionBase<T> * distribution; }; /* -------------------------------------------------------------------------- */ template <typename T> inline std::ostream & operator<<(std::ostream & stream, RandomDistributionBase<T> & _this) { _this.printself(stream); return stream; } /* -------------------------------------------------------------------------- */ template <typename T> inline std::ostream & operator<<(std::ostream & stream, RandomParameter<T> & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_AKA_RANDOM_GENERATOR_HH__ */ diff --git a/src/common/aka_static_memory.cc b/src/common/aka_static_memory.cc index 7a7a48ce5..7d8709f47 100644 --- a/src/common/aka_static_memory.cc +++ b/src/common/aka_static_memory.cc @@ -1,156 +1,156 @@ /** * @file aka_static_memory.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Wed Jan 06 2016 * * @brief Memory management * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <stdexcept> #include <sstream> /* -------------------------------------------------------------------------- */ #include "aka_static_memory.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { bool StaticMemory::is_instantiated = false; StaticMemory * StaticMemory::single_static_memory = NULL; UInt StaticMemory::nb_reference = 0; /* -------------------------------------------------------------------------- */ StaticMemory & StaticMemory::getStaticMemory() { if(!single_static_memory) { single_static_memory = new StaticMemory(); is_instantiated = true; } nb_reference++; return *single_static_memory; } /* -------------------------------------------------------------------------- */ void StaticMemory::destroy() { nb_reference--; if(nb_reference == 0) { delete single_static_memory; } } /* -------------------------------------------------------------------------- */ StaticMemory::~StaticMemory() { AKANTU_DEBUG_IN(); MemoryMap::iterator memory_it; for(memory_it = memories.begin(); memory_it != memories.end(); ++memory_it) { ArrayMap::iterator vector_it; for(vector_it = (memory_it->second).begin(); vector_it != (memory_it->second).end(); ++vector_it) { delete vector_it->second; } (memory_it->second).clear(); } memories.clear(); is_instantiated = false; StaticMemory::single_static_memory = NULL; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void StaticMemory::sfree(const MemoryID & memory_id, const ID & name) { AKANTU_DEBUG_IN(); try { ArrayMap & vectors = const_cast<ArrayMap &>(getMemory(memory_id)); ArrayMap::iterator vector_it; vector_it = vectors.find(name); if(vector_it != vectors.end()) { AKANTU_DEBUG_INFO("Array " << name << " removed from the static memory number " << memory_id); delete vector_it->second; vectors.erase(vector_it); AKANTU_DEBUG_OUT(); return; } } catch (debug::Exception e) { AKANTU_EXCEPTION("The memory " << memory_id << " does not exist (perhaps already freed) [" << e.what() << "]"); AKANTU_DEBUG_OUT(); return; } AKANTU_DEBUG_INFO("The vector " << name << " does not exist (perhaps already freed)"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void StaticMemory::printself(std::ostream & stream, int indent) const{ std::string space = ""; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); std::streamsize prec = stream.precision(); stream.precision(2); stream << space << "StaticMemory [" << std::endl; UInt nb_memories = memories.size(); stream << space << " + nb memories : " << nb_memories << std::endl; Real tot_size = 0; MemoryMap::const_iterator memory_it; for(memory_it = memories.begin(); memory_it != memories.end(); ++memory_it) { Real mem_size = 0; stream << space << AKANTU_INDENT << "Memory [" << std::endl; UInt mem_id = memory_it->first; stream << space << AKANTU_INDENT << " + memory id : " << mem_id << std::endl; UInt nb_vectors = (memory_it->second).size(); stream << space << AKANTU_INDENT << " + nb vectors : " << nb_vectors << std::endl; stream.precision(prec); ArrayMap::const_iterator vector_it; for(vector_it = (memory_it->second).begin(); vector_it != (memory_it->second).end(); ++vector_it) { (vector_it->second)->printself(stream, indent + 2); mem_size += (vector_it->second)->getMemorySize(); } stream << space << AKANTU_INDENT << " + total size : " << printMemorySize<char>(mem_size) << std::endl; stream << space << AKANTU_INDENT << "]" << std::endl; tot_size += mem_size; } stream << space << " + total size : " << printMemorySize<char>(tot_size) << std::endl; stream << space << "]" << std::endl; stream.precision(prec); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/common/aka_static_memory.hh b/src/common/aka_static_memory.hh index 912e30d93..43e4a4415 100644 --- a/src/common/aka_static_memory.hh +++ b/src/common/aka_static_memory.hh @@ -1,157 +1,157 @@ /** * @file aka_static_memory.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief Memory management * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * * @section DESCRIPTION * * The class handling the memory, allocation/reallocation/desallocation * The objects can register their array and ask for allocation or realocation * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_STATIC_MEMORY_HH__ #define __AKANTU_STATIC_MEMORY_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_array.hh" /* -------------------------------------------------------------------------- */ #include <map> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { typedef std::map<ID, ArrayBase *> ArrayMap; typedef std::map<MemoryID, ArrayMap> MemoryMap; /** * @class StaticMemory * @brief Class for memory management common to all objects (this class as to * be accessed by an interface class memory) */ class StaticMemory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ private: /// Default constructor StaticMemory(){}; public: virtual ~StaticMemory(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// Get the global instance of the StaticMemory static StaticMemory & getStaticMemory(); static bool isInstantiated() { return is_instantiated; }; /// remove a reference on the static memory void destroy(); /// access to an Array inline const ArrayBase & getArray(const MemoryID & memory_id, const ID & name) const; /// get all vectors of a memory inline const ArrayMap & getMemory(const MemoryID & memory_id) const; /* ------------------------------------------------------------------------ */ /* Class Methods */ /* ------------------------------------------------------------------------ */ public: /** * Allocation of an array of type * * @param memory_id the id of the memory accessing to the static memory * @param name name of the array (for example connectivity) * @param size number of size (for example number of nodes) * @param nb_component number of component (for example spatial dimension) * @param type the type code of the array to be allocated * * @return pointer to an array of size nb_tupes * nb_component * sizeof(T) */ template <typename T> Array<T> & smalloc(const MemoryID & memory_id, const ID & name, UInt size, UInt nb_component); template <typename T> Array<T> & smalloc(const MemoryID & memory_id, const ID & name, UInt size, UInt nb_component, const T & init_value); /** * free the memory associated to the array name * * @param memory_id the id of the memory accessing to the static memory * @param name the name of an existing array */ void sfree(const MemoryID & memory_id, const ID & name); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// is the static memory instantiated static bool is_instantiated; /// unique instance of the StaticMemory static StaticMemory * single_static_memory; /// map of all allocated arrays, indexed by their names MemoryMap memories; /// number of references on the static memory static UInt nb_reference; }; #include "aka_static_memory_tmpl.hh" #include "aka_static_memory_inline_impl.cc" /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const StaticMemory & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_STATIC_MEMORY_HH__ */ diff --git a/src/common/aka_typelist.hh b/src/common/aka_typelist.hh index 8fa5a6444..d4d5d22df 100644 --- a/src/common/aka_typelist.hh +++ b/src/common/aka_typelist.hh @@ -1,184 +1,184 @@ /** * @file aka_typelist.hh * * @author Alejandro M. Aragón <alejandro.aragon@epfl.ch> * * @date creation: Fri Jan 04 2013 * @date last modification: Sun Oct 19 2014 * * @brief Objects that support the visitor design pattern * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_TYPELIST_HH__ #define __AKANTU_TYPELIST_HH__ #include "aka_common.hh" -__BEGIN_AKANTU__ +namespace akantu { struct Empty_type {}; class Null_type {}; template <class T, class U> struct Typelist { typedef T Head; typedef U Tail; }; template < typename T1 = Null_type, typename T2 = Null_type, typename T3 = Null_type, typename T4 = Null_type, typename T5 = Null_type, typename T6 = Null_type, typename T7 = Null_type, typename T8 = Null_type, typename T9 = Null_type, typename T10 = Null_type, typename T11 = Null_type, typename T12 = Null_type, typename T13 = Null_type, typename T14 = Null_type, typename T15 = Null_type, typename T16 = Null_type, typename T17 = Null_type, typename T18 = Null_type, typename T19 = Null_type, typename T20 = Null_type > struct MakeTypelist { private: typedef typename MakeTypelist < T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20 > ::Result TailResult; public: typedef Typelist<T1, TailResult> Result; }; template<> struct MakeTypelist<> { typedef Null_type Result; }; //////////////////////////////////////////////////////////////////////////////// // class template Length // Computes the length of a typelist // Invocation (TList is a typelist): // Length<TList>::value // returns a compile-time constant containing the length of TList, not counting // the end terminator (which by convention is Null_type) //////////////////////////////////////////////////////////////////////////////// template <class TList> struct Length; template <> struct Length<Null_type> { enum { value = 0 }; }; template <class T, class U> struct Length< Typelist<T, U> > { enum { value = 1 + Length<U>::value }; }; //////////////////////////////////////////////////////////////////////////////// // class template TypeAt // Finds the type at a given index in a typelist // Invocation (TList is a typelist and index is a compile-time integral // constant): // TypeAt<TList, index>::Result // returns the type in position 'index' in TList // If you pass an out-of-bounds index, the result is a compile-time error //////////////////////////////////////////////////////////////////////////////// template <class TList, unsigned int index> struct TypeAt; template <class Head, class Tail> struct TypeAt<Typelist<Head, Tail>, 0> { typedef Head Result; }; template <class Head, class Tail, unsigned int i> struct TypeAt<Typelist<Head, Tail>, i> { typedef typename TypeAt<Tail, i - 1>::Result Result; }; //////////////////////////////////////////////////////////////////////////////// // class template Erase // Erases the first occurence, if any, of a type in a typelist // Invocation (TList is a typelist and T is a type): // Erase<TList, T>::Result // returns a typelist that is TList without the first occurence of T //////////////////////////////////////////////////////////////////////////////// template <class TList, class T> struct Erase; template <class T> // Specialization 1 struct Erase<Null_type, T> { typedef Null_type Result; }; template <class T, class Tail> // Specialization 2 struct Erase<Typelist<T, Tail>, T> { typedef Tail Result; }; template <class Head, class Tail, class T> // Specialization 3 struct Erase<Typelist<Head, Tail>, T> { typedef Typelist<Head, typename Erase<Tail, T>::Result> Result; }; template <class TList, class T> struct IndexOf; template <class T> struct IndexOf<Null_type, T> { enum { value = -1 }; }; template <class T, class Tail> struct IndexOf<Typelist<T, Tail>, T> { enum { value = 0 }; }; template <class Head, class Tail, class T> struct IndexOf<Typelist<Head, Tail>, T> { private: enum { temp = IndexOf<Tail, T>::value }; public: enum { value = (temp == -1 ? -1 : 1 + temp) }; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_TYPELIST_HH__ */ diff --git a/src/common/aka_types.hh b/src/common/aka_types.hh index 0e467af92..fd25e8b19 100644 --- a/src/common/aka_types.hh +++ b/src/common/aka_types.hh @@ -1,1236 +1,1236 @@ /** * @file aka_types.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Feb 17 2011 * @date last modification: Fri Jan 22 2016 * * @brief description of the "simple" types * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_error.hh" #include "aka_fwd.hh" #include "aka_math.hh" /* -------------------------------------------------------------------------- */ #include <initializer_list> #include <iomanip> #include <type_traits> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_TYPES_HH__ #define __AKANTU_AKA_TYPES_HH__ -__BEGIN_AKANTU__ +namespace akantu { enum NormType { L_1 = 1, L_2 = 2, L_inf = UInt(-1) }; /** * DimHelper is a class to generalize the setup of a dim array from 3 * values. This gives a common interface in the TensorStorage class * independently of its derived inheritance (Vector, Matrix, Tensor3) * @tparam dim */ template <UInt dim> struct DimHelper { static inline void setDims(UInt m, UInt n, UInt p, UInt dims[dim]); }; /* -------------------------------------------------------------------------- */ template <> struct DimHelper<1> { static inline void setDims(UInt m, __attribute__((unused)) UInt n, __attribute__((unused)) UInt p, UInt dims[1]) { dims[0] = m; } }; /* -------------------------------------------------------------------------- */ template <> struct DimHelper<2> { static inline void setDims(UInt m, UInt n, __attribute__((unused)) UInt p, UInt dims[2]) { dims[0] = m; dims[1] = n; } }; /* -------------------------------------------------------------------------- */ template <> struct DimHelper<3> { static inline void setDims(UInt m, UInt n, UInt p, UInt dims[3]) { dims[0] = m; dims[1] = n; dims[2] = p; } }; /* -------------------------------------------------------------------------- */ template <typename T, UInt ndim, class RetType> class TensorStorage; /* -------------------------------------------------------------------------- */ /* Proxy classes */ /* -------------------------------------------------------------------------- */ namespace tensors { template <class A, class B> struct is_copyable { enum : bool { value = false }; }; template <class A> struct is_copyable<A, A> { enum : bool { value = true }; }; template <class A> struct is_copyable<A, typename A::RetType> { enum : bool { value = true }; }; template <class A> struct is_copyable<A, typename A::RetType::proxy> { enum : bool { value = true }; }; } // namespace tensors /** * @class TensorProxy aka_types.hh * @desc The TensorProxy class is a proxy class to the TensorStorage it handles * the * wrapped case. That is to say if an accessor should give access to a Tensor * wrapped on some data, like the Array<T>::iterator they can return a * TensorProxy that will be automatically transformed as a TensorStorage wrapped * on the same data * @tparam T stored type * @tparam ndim order of the tensor * @tparam RetType real derived type */ template <typename T, UInt ndim, class _RetType> class TensorProxy { protected: using RetTypeProxy = typename _RetType::proxy; TensorProxy(T * data, UInt m, UInt n, UInt p) { DimHelper<ndim>::setDims(m, n, p, this->n); this->values = data; } template <class Other, typename = std::enable_if_t< tensors::is_copyable<TensorProxy, Other>::value>> explicit TensorProxy(const Other & other) { this->values = other.storage(); for (UInt i = 0; i < ndim; ++i) this->n[i] = other.size(i); } public: using RetType = _RetType; operator RetType() { return RetType(static_cast<RetTypeProxy &>(*this)); } UInt size(UInt i) const { AKANTU_DEBUG_ASSERT(i < ndim, "This tensor has only " << ndim << " dimensions, not " << (i + 1)); return n[i]; } inline UInt size() const { UInt _size = 1; for (UInt d = 0; d < ndim; ++d) _size *= this->n[d]; return _size; } T * storage() const { return values; } template <class Other, typename = std::enable_if_t< tensors::is_copyable<TensorProxy, Other>::value>> inline TensorProxy & operator=(const Other & other) { AKANTU_DEBUG_ASSERT( other.size() == this->size(), "You are trying to copy two tensors with different sizes"); memcpy(this->values, other.storage(), this->size() * sizeof(T)); return *this; } // template <class Other, typename = std::enable_if_t< // tensors::is_copyable<TensorProxy, Other>::value>> // inline TensorProxy & operator=(const Other && other) { // AKANTU_DEBUG_ASSERT( // other.size() == this->size(), // "You are trying to copy two tensors with different sizes"); // memcpy(this->values, other.storage(), this->size() * sizeof(T)); // return *this; // } template <typename O> inline RetTypeProxy & operator*=(const O & o) { RetType(*this) *= o; return static_cast<RetTypeProxy &>(*this); } template <typename O> inline RetTypeProxy & operator/=(const O & o) { RetType(*this) /= o; return static_cast<RetTypeProxy &>(*this); } protected: T * values; UInt n[ndim]; }; /* -------------------------------------------------------------------------- */ template <typename T> class VectorProxy : public TensorProxy<T, 1, Vector<T>> { using parent = TensorProxy<T, 1, Vector<T>>; using type = Vector<T>; public: VectorProxy(T * data, UInt n) : parent(data, n, 0, 0) {} template <class Other> explicit VectorProxy(Other & src) : parent(src) {} /* ---------------------------------------------------------------------- */ template <class Other> inline VectorProxy<T> & operator=(const Other & other) { parent::operator=(other); return *this; } // inline VectorProxy<T> & operator=(const VectorProxy && other) { // parent::operator=(other); // return *this; // } /* ------------------------------------------------------------------------ */ T & operator()(UInt index) { return this->values[index]; }; const T & operator()(UInt index) const { return this->values[index]; }; }; template <typename T> class MatrixProxy : public TensorProxy<T, 2, Matrix<T>> { using parent = TensorProxy<T, 2, Matrix<T>>; using type = Matrix<T>; public: MatrixProxy(T * data, UInt m, UInt n) : parent(data, m, n, 0) {} template <class Other> explicit MatrixProxy(Other & src) : parent(src) {} /* ---------------------------------------------------------------------- */ template <class Other> inline MatrixProxy<T> & operator=(const Other & other) { parent::operator=(other); return *this; } }; template <typename T> class Tensor3Proxy : public TensorProxy<T, 3, Tensor3<T>> { typedef TensorProxy<T, 3, Tensor3<T>> parent; using type = Tensor3<T>; public: Tensor3Proxy(T * data, UInt m, UInt n, UInt k) : parent(data, m, n, k) {} Tensor3Proxy(const Tensor3Proxy & src) : parent(src) {} Tensor3Proxy(const Tensor3<T> & src) : parent(src) {} /* ---------------------------------------------------------------------- */ template <class Other> inline Tensor3Proxy<T> & operator=(const Other & other) { parent::operator=(other); return *this; } }; /* -------------------------------------------------------------------------- */ /* Tensor base class */ /* -------------------------------------------------------------------------- */ template <typename T, UInt ndim, class RetType> class TensorStorage { public: using value_type = T; protected: template <class TensorType> void copySize(const TensorType & src) { for (UInt d = 0; d < ndim; ++d) this->n[d] = src.size(d); this->_size = src.size(); } TensorStorage() : values(nullptr) { for (UInt d = 0; d < ndim; ++d) this->n[d] = 0; _size = 0; } TensorStorage(const TensorProxy<T, ndim, RetType> & proxy) { this->copySize(proxy); this->values = proxy.storage(); this->wrapped = true; } protected: TensorStorage(const TensorStorage & src) = delete; public: TensorStorage(const TensorStorage & src, bool deep_copy) : values(nullptr), wrapped(false) { if (deep_copy) this->deepCopy(src); else this->shallowCopy(src); } protected: TensorStorage(UInt m, UInt n, UInt p, const T & def) { DimHelper<ndim>::setDims(m, n, p, this->n); this->computeSize(); this->values = new T[this->_size]; this->set(def); this->wrapped = false; } TensorStorage(T * data, UInt m, UInt n, UInt p) { DimHelper<ndim>::setDims(m, n, p, this->n); this->computeSize(); this->values = data; this->wrapped = true; } public: /* ------------------------------------------------------------------------ */ template <class TensorType> inline void shallowCopy(const TensorType & src) { this->copySize(src); if (!this->wrapped) delete[] this->values; this->values = src.storage(); this->wrapped = true; } /* ------------------------------------------------------------------------ */ template <class TensorType> inline void deepCopy(const TensorType & src) { this->copySize(src); if (!this->wrapped) delete[] this->values; this->values = new T[this->_size]; memcpy((void *)this->values, (void *)src.storage(), this->_size * sizeof(T)); this->wrapped = false; } virtual ~TensorStorage() { if (!this->wrapped) delete[] this->values; } /* ------------------------------------------------------------------------ */ inline TensorStorage & operator=(const RetType & src) { if (this != &src) { if (this->wrapped) { // this test is not sufficient for Tensor of order higher than 1 AKANTU_DEBUG_ASSERT(this->_size == src.size(), "Tensors of different size"); memcpy((void *)this->values, (void *)src.storage(), this->_size * sizeof(T)); } else { deepCopy(src); } } return *this; } /* ------------------------------------------------------------------------ */ template <class R> inline RetType & operator+=(const TensorStorage<T, ndim, R> & other) { T * a = this->storage(); T * b = other.storage(); AKANTU_DEBUG_ASSERT( _size == other.size(), "The two tensors do not have the same size, they cannot be subtracted"); for (UInt i = 0; i < _size; ++i) *(a++) += *(b++); return *(static_cast<RetType *>(this)); } /* ------------------------------------------------------------------------ */ template <class R> inline RetType & operator-=(const TensorStorage<T, ndim, R> & other) { T * a = this->storage(); T * b = other.storage(); AKANTU_DEBUG_ASSERT( _size == other.size(), "The two tensors do not have the same size, they cannot be subtracted"); for (UInt i = 0; i < _size; ++i) *(a++) -= *(b++); return *(static_cast<RetType *>(this)); } /* ------------------------------------------------------------------------ */ inline RetType & operator+=(const T & x) { T * a = this->values; for (UInt i = 0; i < _size; ++i) *(a++) += x; return *(static_cast<RetType *>(this)); } /* ------------------------------------------------------------------------ */ inline RetType & operator-=(const T & x) { T * a = this->values; for (UInt i = 0; i < _size; ++i) *(a++) -= x; return *(static_cast<RetType *>(this)); } /* ------------------------------------------------------------------------ */ inline RetType & operator*=(const T & x) { T * a = this->storage(); for (UInt i = 0; i < _size; ++i) *(a++) *= x; return *(static_cast<RetType *>(this)); } /* ---------------------------------------------------------------------- */ inline RetType & operator/=(const T & x) { T * a = this->values; for (UInt i = 0; i < _size; ++i) *(a++) /= x; return *(static_cast<RetType *>(this)); } /// Y = \alpha X + Y inline RetType & aXplusY(const TensorStorage & other, const T & alpha = 1.) { AKANTU_DEBUG_ASSERT( _size == other.size(), "The two tensors do not have the same size, they cannot be subtracted"); Math::aXplusY(this->_size, alpha, other.storage(), this->storage()); return *(static_cast<RetType *>(this)); } /* ------------------------------------------------------------------------ */ T * storage() const { return values; } UInt size() const { return _size; } UInt size(UInt i) const { AKANTU_DEBUG_ASSERT(i < ndim, "This tensor has only " << ndim << " dimensions, not " << (i + 1)); return n[i]; }; /* ------------------------------------------------------------------------ */ inline void clear() { memset(values, 0, _size * sizeof(T)); }; inline void set(const T & t) { std::fill_n(values, _size, t); }; template <class TensorType> inline void copy(const TensorType & other) { AKANTU_DEBUG_ASSERT( _size == other.size(), "The two tensors do not have the same size, they cannot be copied"); memcpy(values, other.storage(), _size * sizeof(T)); } bool isWrapped() const { return this->wrapped; } protected: friend class Array<T>; inline void computeSize() { _size = 1; for (UInt d = 0; d < ndim; ++d) _size *= this->n[d]; } protected: template <typename R, NormType norm_type> struct NormHelper { template <class Ten> static R norm(const Ten & ten) { R _norm = 0.; R * it = ten.storage(); R * end = ten.storage() + ten.size(); for (; it < end; ++it) _norm += std::pow(std::abs(*it), norm_type); return std::pow(_norm, 1. / norm_type); } }; template <typename R> struct NormHelper<R, L_1> { template <class Ten> static R norm(const Ten & ten) { R _norm = 0.; R * it = ten.storage(); R * end = ten.storage() + ten.size(); for (; it < end; ++it) _norm += std::abs(*it); return _norm; } }; template <typename R> struct NormHelper<R, L_2> { template <class Ten> static R norm(const Ten & ten) { R _norm = 0.; R * it = ten.storage(); R * end = ten.storage() + ten.size(); for (; it < end; ++it) _norm += *it * *it; return sqrt(_norm); } }; template <typename R> struct NormHelper<R, L_inf> { template <class Ten> static R norm(const Ten & ten) { R _norm = 0.; R * it = ten.storage(); R * end = ten.storage() + ten.size(); for (; it < end; ++it) _norm = std::max(std::abs(*it), _norm); return _norm; } }; public: /*----------------------------------------------------------------------- */ /// "Entrywise" norm norm<L_p> @f[ \|\boldsymbol{T}\|_p = \left( /// \sum_i^{n[0]}\sum_j^{n[1]}\sum_k^{n[2]} |T_{ijk}|^p \right)^{\frac{1}{p}} /// @f] template <NormType norm_type> inline T norm() const { return NormHelper<T, norm_type>::norm(*this); } protected: UInt n[ndim]; UInt _size; T * values; bool wrapped{false}; }; // template <typename T, UInt ndim, class RetType> // inline TensorProxy<T, ndim, RetType>::TensorProxy( // const TensorStorage<T, ndim, RetType> & other) { // this->values = other.storage(); // for (UInt i = 0; i < ndim; ++i) // this->n[i] = other.size(i); // } /* -------------------------------------------------------------------------- */ /* Vector */ /* -------------------------------------------------------------------------- */ template <typename T> class Vector : public TensorStorage<T, 1, Vector<T>> { typedef TensorStorage<T, 1, Vector<T>> parent; public: using value_type = typename parent::value_type; using proxy = VectorProxy<T>; public: Vector() : parent() {} explicit Vector(UInt n, const T & def = T()) : parent(n, 0, 0, def) {} Vector(T * data, UInt n) : parent(data, n, 0, 0) {} Vector(const Vector & src, bool deep_copy = true) : parent(src, deep_copy) {} Vector(const VectorProxy<T> & src) : parent(src) {} Vector(std::initializer_list<T> list) : parent(list.size(), 0, 0, T()) { UInt i = 0; for (auto val : list) { operator()(i++) = val; } } public: ~Vector() override = default; /* ------------------------------------------------------------------------ */ inline Vector & operator=(const Vector & src) { parent::operator=(src); return *this; } /* ------------------------------------------------------------------------ */ inline T & operator()(UInt i) { AKANTU_DEBUG_ASSERT((i < this->n[0]), "Access out of the vector! " << "Index (" << i << ") is out of the vector of size (" << this->n[0] << ")"); return *(this->values + i); } inline const T & operator()(UInt i) const { AKANTU_DEBUG_ASSERT((i < this->n[0]), "Access out of the vector! " << "Index (" << i << ") is out of the vector of size (" << this->n[0] << ")"); return *(this->values + i); } inline T & operator[](UInt i) { return this->operator()(i); } inline const T & operator[](UInt i) const { return this->operator()(i); } /* ------------------------------------------------------------------------ */ inline Vector<T> & operator*=(Real x) { return parent::operator*=(x); } inline Vector<T> & operator/=(Real x) { return parent::operator/=(x); } /* ------------------------------------------------------------------------ */ inline Vector<T> & operator*=(const Vector<T> & vect) { T * a = this->storage(); T * b = vect.storage(); for (UInt i = 0; i < this->_size; ++i) *(a++) *= *(b++); return *this; } /* ------------------------------------------------------------------------ */ inline Real dot(const Vector<T> & vect) const { return Math::vectorDot(this->values, vect.storage(), this->_size); } /* ------------------------------------------------------------------------ */ inline Real mean() const { Real mean = 0; T * a = this->storage(); for (UInt i = 0; i < this->_size; ++i) mean += *(a++); return mean / this->_size; } /* ------------------------------------------------------------------------ */ inline Vector & crossProduct(const Vector<T> & v1, const Vector<T> & v2) { AKANTU_DEBUG_ASSERT(this->size() == 3, "crossProduct is only defined in 3D (n=" << this->size() << ")"); AKANTU_DEBUG_ASSERT( this->size() == v1.size() && this->size() == v2.size(), "crossProduct is not a valid operation non matching size vectors"); Math::vectorProduct3(v1.storage(), v2.storage(), this->values); return *this; } /* ------------------------------------------------------------------------ */ inline void solve(const Matrix<T> & A, const Vector<T> & b) { AKANTU_DEBUG_ASSERT( this->size() == A.rows() && this->_size == A.cols(), "The size of the solution vector mismatches the size of the matrix"); AKANTU_DEBUG_ASSERT( this->_size == b._size, "The rhs vector has a mismatch in size with the matrix"); Math::solve(this->_size, A.storage(), this->values, b.storage()); } /* ------------------------------------------------------------------------ */ template <bool tr_A> inline void mul(const Matrix<T> & A, const Vector<T> & x, Real alpha = 1.0); /* ------------------------------------------------------------------------ */ inline Real norm() const { return parent::template norm<L_2>(); } template <NormType nt> inline Real norm() const { return parent::template norm<nt>(); } /* ------------------------------------------------------------------------ */ inline void normalize() { Real n = norm(); operator/=(n); } /* ------------------------------------------------------------------------ */ /// norm of (*this - x) inline Real distance(const Vector<T> & y) const { Real * vx = this->values; Real * vy = y.storage(); Real sum_2 = 0; for (UInt i = 0; i < this->_size; ++i, ++vx, ++vy) sum_2 += (*vx - *vy) * (*vx - *vy); return sqrt(sum_2); } /* ------------------------------------------------------------------------ */ inline bool equal(const Vector<T> & v, Real tolerance = Math::getTolerance()) const { T * a = this->storage(); T * b = v.storage(); UInt i = 0; while (i < this->_size && (std::abs(*(a++) - *(b++)) < tolerance)) ++i; return i == this->_size; } /* ------------------------------------------------------------------------ */ inline short compare(const Vector<T> & v, Real tolerance = Math::getTolerance()) const { T * a = this->storage(); T * b = v.storage(); for (UInt i(0); i < this->_size; ++i, ++a, ++b) { if (std::abs(*a - *b) > tolerance) return (((*a - *b) > tolerance) ? 1 : -1); } return 0; } /* ------------------------------------------------------------------------ */ inline bool operator==(const Vector<T> & v) const { return equal(v); } inline bool operator!=(const Vector<T> & v) const { return !operator==(v); } inline bool operator<(const Vector<T> & v) const { return compare(v) == -1; } inline bool operator>(const Vector<T> & v) const { return compare(v) == 1; } /* ------------------------------------------------------------------------ */ /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << "["; for (UInt i = 0; i < this->_size; ++i) { if (i != 0) stream << ", "; stream << this->values[i]; } stream << "]"; } // friend class ::akantu::Array<T>; }; using RVector = Vector<Real>; /* ------------------------------------------------------------------------ */ template <> inline bool Vector<UInt>::equal(const Vector<UInt> & v, __attribute__((unused)) Real tolerance) const { UInt * a = this->storage(); UInt * b = v.storage(); UInt i = 0; while (i < this->_size && (*(a++) == *(b++))) ++i; return i == this->_size; } /* ------------------------------------------------------------------------ */ /* Matrix */ /* ------------------------------------------------------------------------ */ template <typename T> class Matrix : public TensorStorage<T, 2, Matrix<T>> { typedef TensorStorage<T, 2, Matrix<T>> parent; public: using value_type = typename parent::value_type; using proxy = MatrixProxy<T>; public: Matrix() : parent() {} Matrix(UInt m, UInt n, const T & def = T()) : parent(m, n, 0, def) {} Matrix(T * data, UInt m, UInt n) : parent(data, m, n, 0) {} Matrix(const Matrix & src, bool deep_copy = true) : parent(src, deep_copy) {} Matrix(const MatrixProxy<T> & src) : parent(src) {} Matrix(std::initializer_list<std::initializer_list<T>> list) { std::size_t n = 0; std::size_t m = list.size(); for (auto row : list) { n = std::max(n, row.size()); } DimHelper<2>::setDims(m, n, 0, this->n); this->computeSize(); this->values = new T[this->_size]; this->set(0); UInt i = 0, j = 0; for (auto row : list) { for (auto val : row) { at(i, j++) = val; } ++i; j = 0; } } virtual ~Matrix() = default; /* ------------------------------------------------------------------------ */ inline Matrix & operator=(const Matrix & src) { parent::operator=(src); return *this; } public: /* ---------------------------------------------------------------------- */ UInt rows() const { return this->n[0]; } UInt cols() const { return this->n[1]; } /* ---------------------------------------------------------------------- */ inline T & at(UInt i, UInt j) { AKANTU_DEBUG_ASSERT(((i < this->n[0]) && (j < this->n[1])), "Access out of the matrix! " << "Index (" << i << ", " << j << ") is out of the matrix of size (" << this->n[0] << ", " << this->n[1] << ")"); return *(this->values + i + j * this->n[0]); } inline const T & at(UInt i, UInt j) const { AKANTU_DEBUG_ASSERT(((i < this->n[0]) && (j < this->n[1])), "Access out of the matrix! " << "Index (" << i << ", " << j << ") is out of the matrix of size (" << this->n[0] << ", " << this->n[1] << ")"); return *(this->values + i + j * this->n[0]); } /* ------------------------------------------------------------------------ */ inline T & operator()(UInt i, UInt j) { return this->at(i, j); } inline const T & operator()(UInt i, UInt j) const { return this->at(i, j); } /// give a line vector wrapped on the column i inline VectorProxy<T> operator()(UInt j) { AKANTU_DEBUG_ASSERT(j < this->n[1], "Access out of the matrix! " << "You are trying to access the column vector " << j << " in a matrix of size (" << this->n[0] << ", " << this->n[1] << ")"); return VectorProxy<T>(this->values + j * this->n[0], this->n[0]); } inline const VectorProxy<T> operator()(UInt j) const { AKANTU_DEBUG_ASSERT(j < this->n[1], "Access out of the matrix! " << "You are trying to access the column vector " << j << " in a matrix of size (" << this->n[0] << ", " << this->n[1] << ")"); return VectorProxy<T>(this->values + j * this->n[0], this->n[0]); } inline T & operator[](UInt idx) { return *(this->values + idx); }; inline const T & operator[](UInt idx) const { return *(this->values + idx); }; /* ---------------------------------------------------------------------- */ inline Matrix operator*(const Matrix & B) { Matrix C(this->rows(), B.cols()); C.mul<false, false>(*this, B); return C; } /* ----------------------------------------------------------------------- */ inline Matrix & operator*=(const T & x) { return parent::operator*=(x); } inline Matrix & operator*=(const Matrix & B) { Matrix C(*this); this->mul<false, false>(C, B); return *this; } /* ---------------------------------------------------------------------- */ template <bool tr_A, bool tr_B> inline void mul(const Matrix & A, const Matrix & B, T alpha = 1.0) { UInt k = A.cols(); if (tr_A) k = A.rows(); #ifndef AKANTU_NDEBUG if (tr_B) { AKANTU_DEBUG_ASSERT(k == B.cols(), "matrices to multiply have no fit dimensions"); AKANTU_DEBUG_ASSERT(this->cols() == B.rows(), "matrices to multiply have no fit dimensions"); } else { AKANTU_DEBUG_ASSERT(k == B.rows(), "matrices to multiply have no fit dimensions"); AKANTU_DEBUG_ASSERT(this->cols() == B.cols(), "matrices to multiply have no fit dimensions"); } if (tr_A) { AKANTU_DEBUG_ASSERT(this->rows() == A.cols(), "matrices to multiply have no fit dimensions"); } else { AKANTU_DEBUG_ASSERT(this->rows() == A.rows(), "matrices to multiply have no fit dimensions"); } #endif // AKANTU_NDEBUG Math::matMul<tr_A, tr_B>(this->rows(), this->cols(), k, alpha, A.storage(), B.storage(), 0., this->storage()); } /* ---------------------------------------------------------------------- */ inline void outerProduct(const Vector<T> & A, const Vector<T> & B) { AKANTU_DEBUG_ASSERT( A.size() == this->rows() && B.size() == this->cols(), "A and B are not compatible with the size of the matrix"); for (UInt i = 0; i < this->rows(); ++i) { for (UInt j = 0; j < this->cols(); ++j) { this->values[i + j * this->rows()] += A[i] * B[j]; } } } private: class EigenSorter { public: EigenSorter(const Vector<T> & eigs) : eigs(eigs) {} bool operator()(const UInt & a, const UInt & b) const { return (eigs(a) > eigs(b)); } private: const Vector<T> & eigs; }; public: /* ---------------------------------------------------------------------- */ inline void eig(Vector<T> & eigenvalues, Matrix<T> & eigenvectors) const { AKANTU_DEBUG_ASSERT(this->cols() == this->rows(), "eig is not a valid operation on a rectangular matrix"); AKANTU_DEBUG_ASSERT(eigenvalues.size() == this->cols(), "eigenvalues should be of size " << this->cols() << "."); #ifndef AKANTU_NDEBUG if (eigenvectors.storage() != NULL) AKANTU_DEBUG_ASSERT((eigenvectors.rows() == eigenvectors.cols()) && (eigenvectors.rows() == this->cols()), "Eigenvectors needs to be a square matrix of size " << this->cols() << " x " << this->cols() << "."); #endif Matrix<T> tmp = *this; Vector<T> tmp_eigs(eigenvalues.size()); Matrix<T> tmp_eig_vects(eigenvectors.rows(), eigenvectors.cols()); if (tmp_eig_vects.rows() == 0 || tmp_eig_vects.cols() == 0) Math::matrixEig(tmp.cols(), tmp.storage(), tmp_eigs.storage()); else Math::matrixEig(tmp.cols(), tmp.storage(), tmp_eigs.storage(), tmp_eig_vects.storage()); Vector<UInt> perm(eigenvalues.size()); for (UInt i = 0; i < perm.size(); ++i) perm(i) = i; std::sort(perm.storage(), perm.storage() + perm.size(), EigenSorter(tmp_eigs)); for (UInt i = 0; i < perm.size(); ++i) eigenvalues(i) = tmp_eigs(perm(i)); if (tmp_eig_vects.rows() != 0 && tmp_eig_vects.cols() != 0) for (UInt i = 0; i < perm.size(); ++i) { for (UInt j = 0; j < eigenvectors.rows(); ++j) { eigenvectors(j, i) = tmp_eig_vects(j, perm(i)); } } } /* ---------------------------------------------------------------------- */ inline void eig(Vector<T> & eigenvalues) const { Matrix<T> empty; eig(eigenvalues, empty); } /* ---------------------------------------------------------------------- */ inline void eye(T alpha = 1.) { AKANTU_DEBUG_ASSERT(this->cols() == this->rows(), "eye is not a valid operation on a rectangular matrix"); this->clear(); for (UInt i = 0; i < this->cols(); ++i) { this->values[i + i * this->rows()] = alpha; } } /* ---------------------------------------------------------------------- */ static inline Matrix<T> eye(UInt m, T alpha = 1.) { Matrix<T> tmp(m, m); tmp.eye(alpha); return tmp; } /* ---------------------------------------------------------------------- */ inline T trace() const { AKANTU_DEBUG_ASSERT( this->cols() == this->rows(), "trace is not a valid operation on a rectangular matrix"); T trace = 0.; for (UInt i = 0; i < this->rows(); ++i) { trace += this->values[i + i * this->rows()]; } return trace; } /* ---------------------------------------------------------------------- */ inline Matrix transpose() const { Matrix tmp(this->cols(), this->rows()); for (UInt i = 0; i < this->rows(); ++i) { for (UInt j = 0; j < this->cols(); ++j) { tmp(j, i) = operator()(i, j); } } return tmp; } /* ---------------------------------------------------------------------- */ inline void inverse(const Matrix & A) { AKANTU_DEBUG_ASSERT(A.cols() == A.rows(), "inv is not a valid operation on a rectangular matrix"); AKANTU_DEBUG_ASSERT(this->cols() == A.cols(), "the matrix should have the same size as its inverse"); if (this->cols() == 1) *this->values = 1. / *A.storage(); else if (this->cols() == 2) Math::inv2(A.storage(), this->values); else if (this->cols() == 3) Math::inv3(A.storage(), this->values); else Math::inv(this->cols(), A.storage(), this->values); } /* --------------------------------------------------------------------- */ inline T det() const { AKANTU_DEBUG_ASSERT(this->cols() == this->rows(), "inv is not a valid operation on a rectangular matrix"); if (this->cols() == 1) return *(this->values); else if (this->cols() == 2) return Math::det2(this->values); else if (this->cols() == 3) return Math::det3(this->values); else return Math::det(this->cols(), this->values); } /* --------------------------------------------------------------------- */ inline T doubleDot(const Matrix<T> & other) const { AKANTU_DEBUG_ASSERT( this->cols() == this->rows(), "doubleDot is not a valid operation on a rectangular matrix"); if (this->cols() == 1) return *(this->values) * *(other.storage()); else if (this->cols() == 2) return Math::matrixDoubleDot22(this->values, other.storage()); else if (this->cols() == 3) return Math::matrixDoubleDot33(this->values, other.storage()); else AKANTU_DEBUG_ERROR("doubleDot is not defined for other spatial dimensions" << " than 1, 2 or 3."); return T(); } /* ---------------------------------------------------------------------- */ /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << "["; for (UInt i = 0; i < this->n[0]; ++i) { if (i != 0) stream << ", "; stream << "["; for (UInt j = 0; j < this->n[1]; ++j) { if (j != 0) stream << ", "; stream << operator()(i, j); } stream << "]"; } stream << "]"; }; }; /* ------------------------------------------------------------------------ */ template <typename T> template <bool tr_A> inline void Vector<T>::mul(const Matrix<T> & A, const Vector<T> & x, Real alpha) { #ifndef AKANTU_NDEBUG UInt n = x.size(); if (tr_A) { AKANTU_DEBUG_ASSERT(n == A.rows(), "matrix and vector to multiply have no fit dimensions"); AKANTU_DEBUG_ASSERT(this->size() == A.cols(), "matrix and vector to multiply have no fit dimensions"); } else { AKANTU_DEBUG_ASSERT(n == A.cols(), "matrix and vector to multiply have no fit dimensions"); AKANTU_DEBUG_ASSERT(this->size() == A.rows(), "matrix and vector to multiply have no fit dimensions"); } #endif Math::matVectMul<tr_A>(A.rows(), A.cols(), alpha, A.storage(), x.storage(), 0., this->storage()); } /* -------------------------------------------------------------------------- */ template <typename T> inline std::ostream & operator<<(std::ostream & stream, const Matrix<T> & _this) { _this.printself(stream); return stream; } /* -------------------------------------------------------------------------- */ template <typename T> inline std::ostream & operator<<(std::ostream & stream, const Vector<T> & _this) { _this.printself(stream); return stream; } /* ------------------------------------------------------------------------ */ /* Tensor3 */ /* ------------------------------------------------------------------------ */ template <typename T> class Tensor3 : public TensorStorage<T, 3, Tensor3<T>> { typedef TensorStorage<T, 3, Tensor3<T>> parent; public: using value_type = typename parent::value_type; using proxy = Tensor3Proxy<T>; public: Tensor3() : parent(){}; Tensor3(UInt m, UInt n, UInt p, const T & def = T()) : parent(m, n, p, def) {} Tensor3(T * data, UInt m, UInt n, UInt p) : parent(data, m, n, p) {} Tensor3(const Tensor3 & src, bool deep_copy = true) : parent(src, deep_copy) {} public: /* ------------------------------------------------------------------------ */ inline Tensor3 & operator=(const Tensor3 & src) { parent::operator=(src); return *this; } /* ---------------------------------------------------------------------- */ inline T & operator()(UInt i, UInt j, UInt k) { AKANTU_DEBUG_ASSERT( (i < this->n[0]) && (j < this->n[1]) && (k < this->n[2]), "Access out of the tensor3! " << "You are trying to access the element " << "(" << i << ", " << j << ", " << k << ") in a tensor of size (" << this->n[0] << ", " << this->n[1] << ", " << this->n[2] << ")"); return *(this->values + (k * this->n[0] + i) * this->n[1] + j); } inline const T & operator()(UInt i, UInt j, UInt k) const { AKANTU_DEBUG_ASSERT( (i < this->n[0]) && (j < this->n[1]) && (k < this->n[2]), "Access out of the tensor3! " << "You are trying to access the element " << "(" << i << ", " << j << ", " << k << ") in a tensor of size (" << this->n[0] << ", " << this->n[1] << ", " << this->n[2] << ")"); return *(this->values + (k * this->n[0] + i) * this->n[1] + j); } inline MatrixProxy<T> operator()(UInt k) { AKANTU_DEBUG_ASSERT((k < this->n[2]), "Access out of the tensor3! " << "You are trying to access the slice " << k << " in a tensor3 of size (" << this->n[0] << ", " << this->n[1] << ", " << this->n[2] << ")"); return MatrixProxy<T>(this->values + k * this->n[0] * this->n[1], this->n[0], this->n[1]); } inline const MatrixProxy<T> operator()(UInt k) const { AKANTU_DEBUG_ASSERT((k < this->n[2]), "Access out of the tensor3! " << "You are trying to access the slice " << k << " in a tensor3 of size (" << this->n[0] << ", " << this->n[1] << ", " << this->n[2] << ")"); return MatrixProxy<T>(this->values + k * this->n[0] * this->n[1], this->n[0], this->n[1]); } inline MatrixProxy<T> operator[](UInt k) { return MatrixProxy<T>(this->values + k * this->n[0] * this->n[1], this->n[0], this->n[1]); } inline const MatrixProxy<T> operator[](UInt k) const { return MatrixProxy<T>(this->values + k * this->n[0] * this->n[1], this->n[0], this->n[1]); } }; /* -------------------------------------------------------------------------- */ // support operations for the creation of other vectors /* -------------------------------------------------------------------------- */ template <typename T> Vector<T> operator*(const T & scalar, const Vector<T> & a) { Vector<T> r(a); r *= scalar; return r; } template <typename T> Vector<T> operator*(const Vector<T> & a, const T & scalar) { Vector<T> r(a); r *= scalar; return r; } template <typename T> Vector<T> operator/(const Vector<T> & a, const T & scalar) { Vector<T> r(a); r /= scalar; return r; } template <typename T> Vector<T> operator+(const Vector<T> & a, const Vector<T> & b) { Vector<T> r(a); r += b; return r; } template <typename T> Vector<T> operator-(const Vector<T> & a, const Vector<T> & b) { Vector<T> r(a); r -= b; return r; } /* -------------------------------------------------------------------------- */ template <typename T> Matrix<T> operator*(const T & scalar, const Matrix<T> & a) { Matrix<T> r(a); r *= scalar; return r; } template <typename T> Matrix<T> operator*(const Matrix<T> & a, const T & scalar) { Matrix<T> r(a); r *= scalar; return r; } template <typename T> Matrix<T> operator/(const Matrix<T> & a, const T & scalar) { Matrix<T> r(a); r /= scalar; return r; } template <typename T> Matrix<T> operator+(const Matrix<T> & a, const Matrix<T> & b) { Matrix<T> r(a); r += b; return r; } template <typename T> Matrix<T> operator-(const Matrix<T> & a, const Matrix<T> & b) { Matrix<T> r(a); r -= b; return r; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_AKA_TYPES_HH__ */ diff --git a/src/common/aka_visitor.hh b/src/common/aka_visitor.hh index cd72e500d..3c3bcd800 100644 --- a/src/common/aka_visitor.hh +++ b/src/common/aka_visitor.hh @@ -1,175 +1,175 @@ /** * @file aka_visitor.hh * * @author Alejandro M. Aragón <alejandro.aragon@epfl.ch> * * @date creation: Fri Jan 04 2013 * @date last modification: Sun Oct 19 2014 * * @brief Objects that support the visitor design pattern * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_VISITOR_HH__ #define __AKANTU_VISITOR_HH__ #include "aka_typelist.hh" -__BEGIN_AKANTU__ +namespace akantu { /////////////////////////////////////////////////////////////////////////// // visitor class template, adapted from the Andrei Alexandrescu's // "Modern C++ Design" enum Visit_type { Mutable, Immutable }; template <class T, typename R = void, Visit_type = Mutable> class StrictVisitor; template <class T, typename R> class StrictVisitor<T, R, Mutable> { public: typedef R ReturnType; typedef T ParamType; virtual ~StrictVisitor() {} virtual ReturnType Visit(ParamType&) = 0; }; template <class T, typename R> class StrictVisitor<T, R, Immutable> { public: typedef R ReturnType; typedef const T ParamType; virtual ~StrictVisitor() {} virtual ReturnType Visit(ParamType&) = 0; }; /// class template StrictVisitor (specialization) template <class Head, class Tail, typename R> class StrictVisitor<Typelist<Head, Tail>, R, Mutable> : public StrictVisitor<Head, R, Mutable>, public StrictVisitor<Tail, R, Mutable> { public: typedef R ReturnType; typedef Head ParamType; // using StrictVisitor<Head, R>::Visit; // using StrictVisitor<Tail, R>::Visit; }; template <class Head, typename R> class StrictVisitor<Typelist<Head, Null_type>, R, Mutable> : public StrictVisitor<Head, R, Mutable> { public: typedef R ReturnType; typedef Head ParamType; using StrictVisitor<Head, R, Mutable>::Visit; }; template <class Head, class Tail, typename R> class StrictVisitor<Typelist<Head, Tail>, R, Immutable> : public StrictVisitor<Head, R, Immutable>, public StrictVisitor<Tail, R, Immutable> { public: typedef R ReturnType; typedef Head ParamType; // using StrictVisitor<Head, R>::Visit; // using StrictVisitor<Tail, R>::Visit; }; template <class Head, typename R> class StrictVisitor<Typelist<Head, Null_type>, R, Immutable> : public StrictVisitor<Head, R, Immutable> { public: typedef R ReturnType; typedef Head ParamType; using StrictVisitor<Head, R, Immutable>::Visit; }; //////////////////////////////////////////////////////////////////////////////// // class template NonStrictVisitor // Implements non-strict visitation (you can implement only part of the Visit // functions) // template <class R> struct DefaultFunctor { template <class T> R operator()(T&) { return R(); } }; template <class T, typename R = void, Visit_type V = Mutable, class F = DefaultFunctor<R> > class BaseVisitorImpl; template <class Head, class Tail, typename R, Visit_type V, class F> class BaseVisitorImpl<Typelist<Head, Tail>, R, V, F> : public StrictVisitor<Head, R, V>, public BaseVisitorImpl<Tail, R, V, F> { public: typedef typename StrictVisitor<Head, R, V>::ParamType ParamType; virtual R Visit(ParamType& h) { return F()(h); } }; template <class Head, typename R, Visit_type V, class F > class BaseVisitorImpl<Typelist<Head, Null_type>, R, V, F> : public StrictVisitor<Head, R, V> { public: typedef typename StrictVisitor<Head, R, V>::ParamType ParamType; virtual R Visit(ParamType& h) { return F()(h); } }; /// Visitor template <class R> struct Strict {}; template <typename R, class TList, Visit_type V = Mutable, template <class> class FunctorPolicy = DefaultFunctor> class Visitor : public BaseVisitorImpl<TList, R, V, FunctorPolicy<R> > { public: typedef R ReturnType; template <class Visited> ReturnType GenericVisit(Visited& host) { StrictVisitor<Visited, ReturnType, V>& subObj = *this; return subObj.Visit(host); } }; template <typename R, class TList, Visit_type V> class Visitor<R, TList, V, Strict> : public StrictVisitor<TList, R, V> { public: typedef R ReturnType; template <class Visited> ReturnType GenericVisit(Visited& host) { StrictVisitor<Visited, ReturnType, V>& subObj = *this; return subObj.Visit(host); } }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_VISITOR_HH__ */ diff --git a/src/common/aka_voigthelper.cc b/src/common/aka_voigthelper.cc index 415141ba7..32111160c 100644 --- a/src/common/aka_voigthelper.cc +++ b/src/common/aka_voigthelper.cc @@ -1,68 +1,68 @@ /** * @file aka_voigthelper.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Till Junge <till.junge@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Dec 20 2013 * @date last modification: Sun Oct 19 2014 * * @brief Voigt indices * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_voigthelper.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* clang-format off */ template <> const UInt VoigtHelper<1>::mat[][1] = {{0}}; template <> const UInt VoigtHelper<2>::mat[][2] = {{0, 2}, {3, 1}}; template <> const UInt VoigtHelper<3>::mat[][3] = {{0, 5, 4}, {8, 1, 3}, {7, 6, 2}}; template <> const UInt VoigtHelper<1>::vec[][2] = {{0, 0}}; template <> const UInt VoigtHelper<2>::vec[][2] = {{0, 0}, {1, 1}, {0, 1}, {1, 0}}; template <> const UInt VoigtHelper<3>::vec[][2] = {{0, 0}, {1, 1}, {2, 2}, {1, 2}, {0, 2}, {0, 1}, {2, 1}, {2, 0}, {1, 0}}; template <> const Real VoigtHelper<1>::factors[] = {1.}; template <> const Real VoigtHelper<2>::factors[] = {1., 1., 2.}; template <> const Real VoigtHelper<3>::factors[] = {1., 1., 1., 2., 2., 2.}; /* clang-format on */ -__END_AKANTU__ +} // akantu diff --git a/src/common/aka_voigthelper.hh b/src/common/aka_voigthelper.hh index 2e85f67e8..9f5ec37b0 100644 --- a/src/common/aka_voigthelper.hh +++ b/src/common/aka_voigthelper.hh @@ -1,77 +1,77 @@ /** * @file aka_voigthelper.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Till Junge <till.junge@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Dec 20 2013 * @date last modification: Fri Jan 22 2016 * * @brief Helper file for Voigt notation * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKA_VOIGTHELPER_HH__ #define __AKA_VOIGTHELPER_HH__ #include "aka_common.hh" #include "aka_types.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt dim> class VoigtHelper { public: /// transfer the B matrix to a Voigt notation B matrix inline static void transferBMatrixToSymVoigtBMatrix( const Matrix<Real> & B, Matrix<Real> & Bvoigt, UInt nb_nodes_per_element); /// transfer the BNL matrix to a Voigt notation B matrix (See Bathe et al. /// IJNME vol 9, 1975) inline static void transferBMatrixToBNL(const Matrix<Real> & B, Matrix<Real> & Bvoigt, UInt nb_nodes_per_element); /// transfer the BL2 matrix to a Voigt notation B matrix (See Bathe et al. /// IJNME vol 9, 1975) inline static void transferBMatrixToBL2(const Matrix<Real> & B, const Matrix<Real> & grad_u, Matrix<Real> & Bvoigt, UInt nb_nodes_per_element); public: const static UInt size; // matrix of vector index I as function of tensor indices i,j const static UInt mat[dim][dim]; // array of matrix indices ij as function of vector index I const static UInt vec[dim * dim][2]; // factors to multiply the strain by for voigt notation const static Real factors[((dim * (dim - 1)) / 2 + dim)]; }; -__END_AKANTU__ +} // akantu #include "aka_voigthelper_tmpl.hh" #endif diff --git a/src/fe_engine/cohesive_element.cc b/src/fe_engine/cohesive_element.cc index 8265aecf5..580aad513 100644 --- a/src/fe_engine/cohesive_element.cc +++ b/src/fe_engine/cohesive_element.cc @@ -1,150 +1,150 @@ /** * @file cohesive_element.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Sun Sep 26 2010 * @date last modification: Mon Sep 14 2015 * * @brief CohesiveElement implementation * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "cohesive_element.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_cohesive_2d_4>::spatial_dimension = 2; template<> UInt GeometricalElement<_gt_cohesive_2d_4>::nb_nodes_per_element = 4; template<> UInt GeometricalElement<_gt_cohesive_2d_4>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_cohesive_2d_4>::nb_facets[] = { 2 }; template<> UInt GeometricalElement<_gt_cohesive_2d_4>::nb_nodes_per_facet[] = { 2 }; template<> UInt GeometricalElement<_gt_cohesive_2d_4>::facet_connectivity_vect[] = {0, 2, 1, 3}; template<> UInt * GeometricalElement<_gt_cohesive_2d_4>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> ElementType ElementClass<_cohesive_2d_4>::facet_type[] = { _segment_2 }; template<> ElementType ElementClass<_cohesive_2d_4>::p1_type = _cohesive_2d_4; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_cohesive_2d_6>::spatial_dimension = 2; template<> UInt GeometricalElement<_gt_cohesive_2d_6>::nb_nodes_per_element = 6; template<> UInt GeometricalElement<_gt_cohesive_2d_6>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_cohesive_2d_6>::nb_facets[] = { 2 }; template<> UInt GeometricalElement<_gt_cohesive_2d_6>::nb_nodes_per_facet[] = { 3 }; template<> UInt GeometricalElement<_gt_cohesive_2d_6>::facet_connectivity_vect[] = {0, 3, 1, 4, 2, 5}; template<> UInt * GeometricalElement<_gt_cohesive_2d_6>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> ElementType ElementClass<_cohesive_2d_6>::facet_type[] = { _segment_3 }; template<> ElementType ElementClass<_cohesive_2d_6>::p1_type = _cohesive_2d_4; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_cohesive_1d_2>::spatial_dimension = 1; template<> UInt GeometricalElement<_gt_cohesive_1d_2>::nb_nodes_per_element = 2; template<> UInt GeometricalElement<_gt_cohesive_1d_2>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_cohesive_1d_2>::nb_facets[] = { 2 }; template<> UInt GeometricalElement<_gt_cohesive_1d_2>::nb_nodes_per_facet[] = { 1 }; template<> UInt GeometricalElement<_gt_cohesive_1d_2>::facet_connectivity_vect[] = {0, 1}; template<> UInt * GeometricalElement<_gt_cohesive_1d_2>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> ElementType ElementClass<_cohesive_1d_2>::facet_type[] = { _point_1 }; template<> ElementType ElementClass<_cohesive_1d_2>::p1_type = _cohesive_1d_2; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_cohesive_3d_6>::spatial_dimension = 3; template<> UInt GeometricalElement<_gt_cohesive_3d_6>::nb_nodes_per_element = 6; template<> UInt GeometricalElement<_gt_cohesive_3d_6>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_cohesive_3d_6>::nb_facets[] = { 2 }; template<> UInt GeometricalElement<_gt_cohesive_3d_6>::nb_nodes_per_facet[] = { 3 }; template<> UInt GeometricalElement<_gt_cohesive_3d_6>::facet_connectivity_vect[] = {0, 3, 1, 4, 2, 5}; template<> UInt * GeometricalElement<_gt_cohesive_3d_6>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> ElementType ElementClass<_cohesive_3d_6>::facet_type[] = { _triangle_3 }; template<> ElementType ElementClass<_cohesive_3d_6>::p1_type = _cohesive_3d_6; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_cohesive_3d_12>::spatial_dimension = 3; template<> UInt GeometricalElement<_gt_cohesive_3d_12>::nb_nodes_per_element = 12; template<> UInt GeometricalElement<_gt_cohesive_3d_12>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_cohesive_3d_12>::nb_facets[] = { 2 }; template<> UInt GeometricalElement<_gt_cohesive_3d_12>::nb_nodes_per_facet[] = { 6 }; template<> UInt GeometricalElement<_gt_cohesive_3d_12>::facet_connectivity_vect[] = {0, 6, 1, 7, 2, 8, 3, 9, 4, 10, 5, 11}; template<> UInt * GeometricalElement<_gt_cohesive_3d_12>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> ElementType ElementClass<_cohesive_3d_12>::facet_type[] = { _triangle_6 }; template<> ElementType ElementClass<_cohesive_3d_12>::p1_type = _cohesive_3d_6; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_cohesive_3d_8>::spatial_dimension = 3; template<> UInt GeometricalElement<_gt_cohesive_3d_8>::nb_nodes_per_element = 8; template<> UInt GeometricalElement<_gt_cohesive_3d_8>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_cohesive_3d_8>::nb_facets[] = { 2 }; template<> UInt GeometricalElement<_gt_cohesive_3d_8>::nb_nodes_per_facet[] = { 4 }; template<> UInt GeometricalElement<_gt_cohesive_3d_8>::facet_connectivity_vect[] = {0, 4, 1, 5, 2, 6, 3, 7}; template<> UInt * GeometricalElement<_gt_cohesive_3d_8>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> ElementType ElementClass<_cohesive_3d_8>::facet_type[] = { _quadrangle_4 }; template<> ElementType ElementClass<_cohesive_3d_8>::p1_type = _cohesive_3d_8; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_cohesive_3d_16>::spatial_dimension = 3; template<> UInt GeometricalElement<_gt_cohesive_3d_16>::nb_nodes_per_element = 16; template<> UInt GeometricalElement<_gt_cohesive_3d_16>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_cohesive_3d_16>::nb_facets[] = { 2 }; template<> UInt GeometricalElement<_gt_cohesive_3d_16>::nb_nodes_per_facet[] = { 8 }; template<> UInt GeometricalElement<_gt_cohesive_3d_16>::facet_connectivity_vect[] = {0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15}; template<> UInt * GeometricalElement<_gt_cohesive_3d_16>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> ElementType ElementClass<_cohesive_3d_16>::facet_type[] = { _quadrangle_8 }; template<> ElementType ElementClass<_cohesive_3d_16>::p1_type = _cohesive_3d_8; /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/fe_engine/cohesive_element.hh b/src/fe_engine/cohesive_element.hh index f5a188c3e..968604ffd 100644 --- a/src/fe_engine/cohesive_element.hh +++ b/src/fe_engine/cohesive_element.hh @@ -1,91 +1,91 @@ /** * @file cohesive_element.hh * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 22 2015 * * @brief Generates the cohesive element structres (defined in * element_class.hh) * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_COHESIVE_ELEMENT_HH__ #define __AKANTU_COHESIVE_ELEMENT_HH__ -__BEGIN_AKANTU__ +namespace akantu { AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_cohesive_2d_4, _gt_cohesive_2d_4, _itp_lagrange_segment_2, _ek_cohesive, 2, _git_segment, 2); AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_cohesive_2d_6, _gt_cohesive_2d_6, _itp_lagrange_segment_3, _ek_cohesive, 2, _git_segment, 3); AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_cohesive_1d_2, _gt_cohesive_1d_2, _itp_lagrange_point_1, _ek_cohesive, 1, _git_point, 1); AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_cohesive_3d_6, _gt_cohesive_3d_6, _itp_lagrange_triangle_3, _ek_cohesive, 3, _git_triangle, 2); AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_cohesive_3d_12, _gt_cohesive_3d_12, _itp_lagrange_triangle_6, _ek_cohesive, 3, _git_triangle, 3); AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_cohesive_3d_8, _gt_cohesive_3d_8, _itp_lagrange_quadrangle_4, _ek_cohesive, 3, _git_segment, 2); AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_cohesive_3d_16, _gt_cohesive_3d_16, _itp_serendip_quadrangle_8, _ek_cohesive, 3, _git_segment, 3); template <ElementType> struct CohesiveFacetProperty { static const ElementType cohesive_type = _not_defined; }; #define AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(ftype, ctype) \ template <> struct CohesiveFacetProperty<ftype> { \ static const ElementType cohesive_type = ctype; \ } AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(_point_1, _cohesive_1d_2); AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(_segment_2, _cohesive_2d_4); AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(_segment_3, _cohesive_2d_6); AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(_triangle_3, _cohesive_3d_6); AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(_triangle_6, _cohesive_3d_12); AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(_quadrangle_4, _cohesive_3d_8); AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(_quadrangle_8, _cohesive_3d_16); -__END_AKANTU__ +} // akantu #endif /* __AKANTU_COHESIVE_ELEMENT_HH__ */ diff --git a/src/fe_engine/element.hh b/src/fe_engine/element.hh index a2e35603e..3541a12e7 100644 --- a/src/fe_engine/element.hh +++ b/src/fe_engine/element.hh @@ -1,127 +1,127 @@ /** * @file element.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Sep 02 2014 * @date last modification: Sat Jul 11 2015 * * @brief Element helper class * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_ELEMENT_HH__ #define __AKANTU_ELEMENT_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* Element */ /* -------------------------------------------------------------------------- */ class Element; extern const Element ElementNull; class Element { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: explicit Element(ElementType type = _not_defined, UInt element = 0, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_regular) : type(type), element(element), ghost_type(ghost_type), kind(kind) {}; Element(const Element & element) { this->type = element.type; this->element = element.element; this->ghost_type = element.ghost_type; this->kind = element.kind; } virtual ~Element() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: inline bool operator==(const Element & elem) const { return ((element == elem.element) && (type == elem.type) && (ghost_type == elem.ghost_type) && (kind == elem.kind)); } inline bool operator!=(const Element & elem) const { return ((element != elem.element) || (type != elem.type) || (ghost_type != elem.ghost_type) || (kind != elem.kind)); } bool operator<(const Element& rhs) const { bool res = (rhs == ElementNull) || ((this->kind < rhs.kind) || ((this->kind == rhs.kind) && ((this->ghost_type < rhs.ghost_type) || ((this->ghost_type == rhs.ghost_type) && ((this->type < rhs.type) || ((this->type == rhs.type) && (this->element < rhs.element))))))); return res; } /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: const ElementType & getType(){return type;} const UInt & getIndex(){return element;}; const GhostType & getGhostType(){return ghost_type;} const ElementKind & getElementKind(){return kind;} /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: ElementType type; UInt element; GhostType ghost_type; ElementKind kind; }; struct CompElementLess { bool operator() (const Element& lhs, const Element& rhs) const { return lhs < rhs; } }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_ELEMENT_HH__ */ diff --git a/src/fe_engine/element_class.cc b/src/fe_engine/element_class.cc index 379148d0f..688de3b4a 100644 --- a/src/fe_engine/element_class.cc +++ b/src/fe_engine/element_class.cc @@ -1,86 +1,86 @@ /** * @file element_class.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Peter Spijker <peter.spijker@epfl.ch> * * @date creation: Tue Jul 20 2010 * @date last modification: Thu Jul 16 2015 * * @brief Common part of element_classes * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ using std::sqrt; -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<> ElementType ElementClass<_not_defined>::p1_type = _not_defined; template<> ElementType ElementClass<_not_defined>::facet_type[] = {_not_defined}; /* -------------------------------------------------------------------------- */ template<> ElementType ElementClass<_point_1>::p1_type = _point_1; template<> ElementType ElementClass<_point_1>::facet_type[] = {_point_1}; /* -------------------------------------------------------------------------- */ template<> ElementType ElementClass<_segment_2>::p1_type = _segment_2; template<> ElementType ElementClass<_segment_2>::facet_type[] = {_point_1}; /* -------------------------------------------------------------------------- */ template<> ElementType ElementClass<_segment_3>::p1_type = _segment_2; template<> ElementType ElementClass<_segment_3>::facet_type[] = {_point_1}; /* -------------------------------------------------------------------------- */ template<> ElementType ElementClass<_triangle_3>::p1_type = _triangle_3; template<> ElementType ElementClass<_triangle_3>::facet_type[] = {_segment_2}; /* -------------------------------------------------------------------------- */ template<> ElementType ElementClass<_triangle_6>::p1_type = _triangle_3; template<> ElementType ElementClass<_triangle_6>::facet_type[] = {_segment_3}; /* -------------------------------------------------------------------------- */ template<> ElementType ElementClass<_tetrahedron_4>::p1_type = _tetrahedron_4; template<> ElementType ElementClass<_tetrahedron_4>::facet_type[]= {_triangle_3}; /* -------------------------------------------------------------------------- */ template<> ElementType ElementClass<_tetrahedron_10>::p1_type = _tetrahedron_4; template<> ElementType ElementClass<_tetrahedron_10>::facet_type[] = {_triangle_6}; /* -------------------------------------------------------------------------- */ template<> ElementType ElementClass<_quadrangle_4>::p1_type = _quadrangle_4; template<> ElementType ElementClass<_quadrangle_4>::facet_type[] = {_segment_2}; /* -------------------------------------------------------------------------- */ template<> ElementType ElementClass<_quadrangle_8>::p1_type = _quadrangle_4; template<> ElementType ElementClass<_quadrangle_8>::facet_type[] = { _segment_3 }; /* -------------------------------------------------------------------------- */ template<> ElementType ElementClass<_hexahedron_8>::p1_type = _hexahedron_8; template<> ElementType ElementClass<_hexahedron_8>::facet_type[] = { _quadrangle_4 }; /* -------------------------------------------------------------------------- */ template<> ElementType ElementClass<_hexahedron_20>::p1_type = _hexahedron_8; template<> ElementType ElementClass<_hexahedron_20>::facet_type[] = { _quadrangle_8 }; /* -------------------------------------------------------------------------- */ template<> ElementType ElementClass<_pentahedron_6>::p1_type = _pentahedron_6; template<> ElementType ElementClass<_pentahedron_6>::facet_type[] = { _triangle_3, _quadrangle_4 }; /* -------------------------------------------------------------------------- */ template<> ElementType ElementClass<_pentahedron_15>::p1_type = _pentahedron_6; template<> ElementType ElementClass<_pentahedron_15>::facet_type[] = { _triangle_6, _quadrangle_8 }; /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/fe_engine/element_class.hh b/src/fe_engine/element_class.hh index 154908799..e8eac82ac 100644 --- a/src/fe_engine/element_class.hh +++ b/src/fe_engine/element_class.hh @@ -1,398 +1,398 @@ /** * @file element_class.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Jan 21 2016 * * @brief Declaration of the ElementClass main class and the * Integration and Interpolation elements * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_types.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ELEMENT_CLASS_HH__ #define __AKANTU_ELEMENT_CLASS_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /// default element class structure template <ElementType element_type> struct ElementClassProperty { static const GeometricalType geometrical_type = _gt_not_defined; static const InterpolationType interpolation_type = _itp_not_defined; static const ElementKind element_kind = _ek_regular; static const UInt spatial_dimension = 0; static const GaussIntegrationType gauss_integration_type = _git_not_defined; static const UInt polynomial_degree = 0; }; /// Macro to generate the element class structures for different element types #define AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(elem_type, geom_type, \ interp_type, elem_kind, sp, \ gauss_int_type, min_int_order) \ template <> struct ElementClassProperty<elem_type> { \ static const GeometricalType geometrical_type = geom_type; \ static const InterpolationType interpolation_type = interp_type; \ static const ElementKind element_kind = elem_kind; \ static const UInt spatial_dimension = sp; \ static const GaussIntegrationType gauss_integration_type = \ gauss_int_type; \ static const UInt polynomial_degree = min_int_order; \ } /* -------------------------------------------------------------------------- */ /* Geometry */ /* -------------------------------------------------------------------------- */ /// Default GeometricalShape structure template <GeometricalType geometrical_type> struct GeometricalShape { static const GeometricalShapeType shape = _gst_point; }; /// Templated GeometricalShape with function contains template <GeometricalShapeType shape> struct GeometricalShapeContains { /// Check if the point (vector in 2 and 3D) at natural coordinate coor template <class vector_type> static inline bool contains(const vector_type & coord); }; /// Macro to generate the GeometricalShape structures for different geometrical /// types #define AKANTU_DEFINE_SHAPE(geom_type, geom_shape) \ template <> struct GeometricalShape<geom_type> { \ static const GeometricalShapeType shape = geom_shape; \ } /* -------------------------------------------------------------------------- */ /// Templated GeometricalElement with function getInradius template <GeometricalType geometrical_type, GeometricalShapeType shape = GeometricalShape<geometrical_type>::shape> class GeometricalElement { public: /// compute the in-radius static inline Real getInradius(__attribute__((unused)) const Matrix<Real> & coord) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// true if the natural coordinates are in the element template <class vector_type> static inline bool contains(const vector_type & coord); public: static AKANTU_GET_MACRO_NOT_CONST(SpatialDimension, spatial_dimension, UInt); static AKANTU_GET_MACRO_NOT_CONST(NbNodesPerElement, nb_nodes_per_element, UInt); static AKANTU_GET_MACRO_NOT_CONST(NbFacetTypes, nb_facet_types, UInt); static inline UInt getNbFacetsPerElement(UInt t); static inline UInt getNbFacetsPerElement(); static inline const MatrixProxy<UInt> getFacetLocalConnectivityPerElement(UInt t = 0); protected: /// Number of nodes per element static UInt nb_nodes_per_element; /// spatial dimension of the element static UInt spatial_dimension; /// number of different facet types static UInt nb_facet_types; /// number of facets for element static UInt nb_facets[]; /// storage of the facet local connectivity static UInt facet_connectivity_vect[]; /// local connectivity of facets static UInt * facet_connectivity[]; private: /// Type of the facet elements static UInt nb_nodes_per_facet[]; }; /* -------------------------------------------------------------------------- */ /* Interpolation */ /* -------------------------------------------------------------------------- */ /// default InterpolationPorperty structure template <InterpolationType interpolation_type> struct InterpolationPorperty { static const InterpolationKind kind = _itk_not_defined; static const UInt nb_nodes_per_element = 0; static const UInt natural_space_dimension = 0; }; /// Macro to generate the InterpolationPorperty structures for different /// interpolation types #define AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(itp_type, itp_kind, \ nb_nodes, ndim) \ template <> struct InterpolationPorperty<itp_type> { \ static const InterpolationKind kind = itp_kind; \ static const UInt nb_nodes_per_element = nb_nodes; \ static const UInt natural_space_dimension = ndim; \ } #include "interpolation_element_tmpl.hh" /* -------------------------------------------------------------------------- */ /// Generic (templated by the enum InterpolationType which specifies the order /// and the dimension of the interpolation) class handling the elemental /// interpolation template <InterpolationType interpolation_type, InterpolationKind kind = InterpolationPorperty<interpolation_type>::kind> class InterpolationElement { public: typedef InterpolationPorperty<interpolation_type> interpolation_property; /// compute the shape values for a given set of points in natural coordinates static inline void computeShapes(const Matrix<Real> & natural_coord, Matrix<Real> & N); /// compute the shape values for a given point in natural coordinates template <class vector_type> static inline void computeShapes(__attribute__((unused)) const vector_type & natural_coord, __attribute__((unused)) vector_type & N) { AKANTU_DEBUG_TO_IMPLEMENT(); } /** * compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the variation of * shape functions along with variation of natural coordinates on a given set * of points in natural coordinates */ static inline void computeDNDS(const Matrix<Real> & natural_coord, Tensor3<Real> & dnds); /** * compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the variation of * shape functions along with * variation of natural coordinates on a given point in natural * coordinates */ template <class vector_type, class matrix_type> static inline void computeDNDS(__attribute__((unused)) const vector_type & natural_coord, __attribute__((unused)) matrix_type & dnds) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute jacobian (or integration variable change factor) for a given point /// in the case of spatial_dimension != natural_space_dimension static inline void computeSpecialJacobian(__attribute__((unused)) const Matrix<Real> & J, __attribute__((unused)) Real & jacobians) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// interpolate a field given (arbitrary) natural coordinates static inline void interpolateOnNaturalCoordinates(const Vector<Real> & natural_coords, const Matrix<Real> & nodal_values, Vector<Real> & interpolated); /// interpolate a field given the shape functions on the interpolation point static inline void interpolate(const Matrix<Real> & nodal_values, const Vector<Real> & shapes, Vector<Real> & interpolated); /// interpolate a field given the shape functions on the interpolations points static inline void interpolate(const Matrix<Real> & nodal_values, const Matrix<Real> & shapes, Matrix<Real> & interpolated); /// compute the gradient of a given field on the given natural coordinates static inline void gradientOnNaturalCoordinates(const Vector<Real> & natural_coords, const Matrix<Real> & f, Matrix<Real> & gradient); public: static AKANTU_GET_MACRO_NOT_CONST( ShapeSize, InterpolationPorperty<interpolation_type>::nb_nodes_per_element, UInt); static AKANTU_GET_MACRO_NOT_CONST( ShapeDerivativesSize, (InterpolationPorperty<interpolation_type>::nb_nodes_per_element * InterpolationPorperty<interpolation_type>::natural_space_dimension), UInt); static AKANTU_GET_MACRO_NOT_CONST( NaturalSpaceDimension, InterpolationPorperty<interpolation_type>::natural_space_dimension, UInt); static AKANTU_GET_MACRO_NOT_CONST( NbNodesPerInterpolationElement, InterpolationPorperty<interpolation_type>::nb_nodes_per_element, UInt); }; /* -------------------------------------------------------------------------- */ /* Integration */ /* -------------------------------------------------------------------------- */ template <GaussIntegrationType git_class, UInt nb_points> struct GaussIntegrationTypeData { /// quadrature points in natural coordinates static Real quad_positions[]; /// weights for the Gauss integration static Real quad_weights[]; }; template <ElementType type, UInt n = ElementClassProperty<type>::polynomial_degree> class GaussIntegrationElement { public: static UInt getNbQuadraturePoints(); static const Matrix<Real> getQuadraturePoints(); static const Vector<Real> getWeights(); }; /* -------------------------------------------------------------------------- */ /* ElementClass */ /* -------------------------------------------------------------------------- */ template <ElementType element_type, ElementKind element_kind = ElementClassProperty<element_type>::element_kind> class ElementClass : public GeometricalElement< ElementClassProperty<element_type>::geometrical_type>, public InterpolationElement< ElementClassProperty<element_type>::interpolation_type> { protected: typedef GeometricalElement< ElementClassProperty<element_type>::geometrical_type> geometrical_element; typedef InterpolationElement<ElementClassProperty< element_type>::interpolation_type> interpolation_element; typedef ElementClassProperty<element_type> element_property; typedef typename interpolation_element::interpolation_property interpolation_property; public: /** * compute @f$ J = \frac{\partial x_j}{\partial s_i} @f$ the variation of real * coordinates along with variation of natural coordinates on a given point in * natural coordinates */ static inline void computeJMat(const Matrix<Real> & dnds, const Matrix<Real> & node_coords, Matrix<Real> & J); /** * compute the Jacobian matrix by computing the variation of real coordinates * along with variation of natural coordinates on a given set of points in * natural coordinates */ static inline void computeJMat(const Tensor3<Real> & dnds, const Matrix<Real> & node_coords, Tensor3<Real> & J); /// compute the jacobians of a serie of natural coordinates static inline void computeJacobian(const Matrix<Real> & natural_coords, const Matrix<Real> & node_coords, Vector<Real> & jacobians); /// compute jacobian (or integration variable change factor) for a set of /// points static inline void computeJacobian(const Tensor3<Real> & J, Vector<Real> & jacobians); /// compute jacobian (or integration variable change factor) for a given point static inline void computeJacobian(const Matrix<Real> & J, Real & jacobians); /// compute shape derivatives (input is dxds) for a set of points static inline void computeShapeDerivatives(const Tensor3<Real> & J, const Tensor3<Real> & dnds, Tensor3<Real> & shape_deriv); /// compute shape derivatives (input is dxds) for a given point static inline void computeShapeDerivatives(const Matrix<Real> & J, const Matrix<Real> & dnds, Matrix<Real> & shape_deriv); /// compute the normal of a surface defined by the function f static inline void computeNormalsOnNaturalCoordinates(const Matrix<Real> & coord, Matrix<Real> & f, Matrix<Real> & normals); /// get natural coordinates from real coordinates static inline void inverseMap(const Vector<Real> & real_coords, const Matrix<Real> & node_coords, Vector<Real> & natural_coords, Real tolerance = 1e-8); /// get natural coordinates from real coordinates static inline void inverseMap(const Matrix<Real> & real_coords, const Matrix<Real> & node_coords, Matrix<Real> & natural_coords, Real tolerance = 1e-8); public: static AKANTU_GET_MACRO_NOT_CONST(Kind, element_kind, ElementKind); static AKANTU_GET_MACRO_NOT_CONST( SpatialDimension, ElementClassProperty<element_type>::spatial_dimension, UInt); static AKANTU_GET_MACRO_NOT_CONST(P1ElementType, p1_type, const ElementType &); static const ElementType & getFacetType(UInt t = 0) { return facet_type[t]; } static ElementType * getFacetTypeInternal() { return facet_type; } protected: /// Type of the facet elements static ElementType facet_type[]; /// type of element P1 associated static ElementType p1_type; }; /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #include "element_class_tmpl.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { #include "element_class_point_1_inline_impl.cc" #include "element_class_segment_2_inline_impl.cc" #include "element_class_segment_3_inline_impl.cc" #include "element_class_triangle_3_inline_impl.cc" #include "element_class_triangle_6_inline_impl.cc" #include "element_class_tetrahedron_4_inline_impl.cc" #include "element_class_tetrahedron_10_inline_impl.cc" #include "element_class_quadrangle_4_inline_impl.cc" #include "element_class_quadrangle_8_inline_impl.cc" #include "element_class_hexahedron_8_inline_impl.cc" #include "element_class_hexahedron_20_inline_impl.cc" #include "element_class_pentahedron_6_inline_impl.cc" #include "element_class_pentahedron_15_inline_impl.cc" -__END_AKANTU__ +} // akantu /* -------------------------------------------------------------------------- */ #if defined(AKANTU_STRUCTURAL_MECHANICS) #include "element_class_structural.hh" #endif #if defined(AKANTU_IGFEM) #include "element_class_igfem.hh" #endif #endif /* __AKANTU_ELEMENT_CLASS_HH__ */ diff --git a/src/fe_engine/element_class_structural.hh b/src/fe_engine/element_class_structural.hh index 7f5c81720..4ef4c017c 100644 --- a/src/fe_engine/element_class_structural.hh +++ b/src/fe_engine/element_class_structural.hh @@ -1,260 +1,260 @@ /** * @file element_class_structural.hh * * @author Fabian Barras <fabian.barras@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Damien Spielmann <damien.spielmann@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Thu Oct 22 2015 * * @brief Specialization of the element classes for structural elements * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <InterpolationType interpolation_type> class InterpolationElement<interpolation_type, _itk_structural> { public: typedef InterpolationPorperty<interpolation_type> interpolation_property; /// compute the shape values for a given set of points in natural coordinates static inline void computeShapes(const Matrix<Real> & natural_coord, Matrix<Real> & N, const Matrix<Real> & real_nodal_coord, UInt n = 0) { UInt nb_points = natural_coord.cols(); for (UInt p = 0; p < nb_points; ++p) { Vector<Real> Np = N(p); computeShapes(natural_coord(p), Np, real_nodal_coord, n); } } /// compute the shape values for a given point in natural coordinates static inline void computeShapes(const Vector<Real> & natural_coord, Vector<Real> & N, const Matrix<Real> & real_nodal_coord, UInt n = 0); /** * compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the variation of * shape functions along with variation of natural coordinates on a given set * of points in natural coordinates */ static inline void computeDNDS(const Matrix<Real> & natural_coord, Tensor3<Real> & dnds, const Matrix<Real> & real_nodal_coord, UInt n = 0) { for (UInt i = 0; i < natural_coord.cols(); ++i) { Matrix<Real> dnds_t = dnds(i); computeDNDS(natural_coord(i), dnds_t, real_nodal_coord, n); } } /** * compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the variation of * shape functions along with * variation of natural coordinates on a given point in natural * coordinates */ static inline void computeDNDS(const Vector<Real> & natural_coord, Matrix<Real> & dnds, const Matrix<Real> & real_nodal_coord, UInt n = 0); public: static AKANTU_GET_MACRO_NOT_CONST(NbShapeFunctions, nb_shape_functions, UInt); static AKANTU_GET_MACRO_NOT_CONST(NbShapeDerivatives, nb_shape_derivatives, UInt); static AKANTU_GET_MACRO_NOT_CONST( ShapeSize, interpolation_property::nb_nodes_per_element, UInt); static AKANTU_GET_MACRO_NOT_CONST( ShapeDerivativesSize, (interpolation_property::nb_nodes_per_element * interpolation_property::natural_space_dimension), UInt); static AKANTU_GET_MACRO_NOT_CONST( NaturalSpaceDimension, interpolation_property::natural_space_dimension, UInt); protected: /// nb shape functions static const UInt nb_shape_functions; static const UInt nb_shape_derivatives; }; /// Macro to generate the element class structures for different structural /// element types /* -------------------------------------------------------------------------- */ #define AKANTU_DEFINE_STRUCTURAL_ELEMENT_CLASS_PROPERTY( \ elem_type, geom_type, interp_type, parent_el_type, elem_kind, sp, \ gauss_int_type, min_int_order) \ template <> struct ElementClassProperty<elem_type> { \ static const GeometricalType geometrical_type = geom_type; \ static const InterpolationType interpolation_type = interp_type; \ static const ElementType parent_element_type = parent_el_type; \ static const ElementKind element_kind = elem_kind; \ static const UInt spatial_dimension = sp; \ static const GaussIntegrationType gauss_integration_type = gauss_int_type; \ static const UInt polynomial_degree = min_int_order; \ } /* -------------------------------------------------------------------------- */ /* ElementClass for structural elements */ /* -------------------------------------------------------------------------- */ template <ElementType element_type> class ElementClass<element_type, _ek_structural> : public GeometricalElement< ElementClassProperty<element_type>::geometrical_type>, public InterpolationElement< ElementClassProperty<element_type>::interpolation_type> { protected: typedef GeometricalElement< ElementClassProperty<element_type>::geometrical_type> geometrical_element; typedef InterpolationElement< ElementClassProperty<element_type>::interpolation_type> interpolation_element; typedef ElementClass<ElementClassProperty<element_type>::parent_element_type> parent_element; public: /// compute shape derivatives (input is dxds) for a set of points static inline void computeShapeDerivatives(const Matrix<Real> & natural_coord, Tensor3<Real> & shape_deriv, const Matrix<Real> & real_nodal_coord, UInt n = 0) { UInt nb_points = natural_coord.cols(); if (element_type == _kirchhoff_shell) { /// TO BE CONTINUED and moved in a _tmpl.hh UInt spatial_dimension = real_nodal_coord.cols(); UInt nb_nodes = real_nodal_coord.rows(); const UInt projected_dim = natural_coord.rows(); Matrix<Real> rotation_matrix(real_nodal_coord); Matrix<Real> rotated_nodal_coord(real_nodal_coord); Matrix<Real> projected_nodal_coord(natural_coord); /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ Matrix<Real> Pe(real_nodal_coord); Matrix<Real> Pg(real_nodal_coord); Matrix<Real> inv_Pg(real_nodal_coord); /// compute matrix Pe Pe.eye(); /// compute matrix Pg Vector<Real> Pg_col_1(spatial_dimension); Pg_col_1(0) = real_nodal_coord(0, 1) - real_nodal_coord(0, 0); Pg_col_1(1) = real_nodal_coord(1, 1) - real_nodal_coord(1, 0); Pg_col_1(2) = real_nodal_coord(2, 1) - real_nodal_coord(2, 0); Vector<Real> Pg_col_2(spatial_dimension); Pg_col_2(0) = real_nodal_coord(0, 2) - real_nodal_coord(0, 0); Pg_col_2(1) = real_nodal_coord(1, 2) - real_nodal_coord(1, 0); Pg_col_2(2) = real_nodal_coord(2, 2) - real_nodal_coord(2, 0); Vector<Real> Pg_col_3(spatial_dimension); Pg_col_3.crossProduct(Pg_col_1, Pg_col_2); for (UInt i = 0; i < nb_points; ++i) { Pg(i, 0) = Pg_col_1(i); Pg(i, 1) = Pg_col_2(i); Pg(i, 2) = Pg_col_3(i); } /// compute inverse of Pg inv_Pg.inverse(Pg); /// compute rotation matrix // rotation_matrix=Pe*inv_Pg; rotation_matrix.eye(); /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ rotated_nodal_coord.mul<false, false>(rotation_matrix, real_nodal_coord); for (UInt i = 0; i < projected_dim; ++i) { for (UInt j = 0; j < nb_points; ++j) { projected_nodal_coord(i, j) = rotated_nodal_coord(i, j); } } Tensor3<Real> dnds(projected_dim, nb_nodes, natural_coord.cols()); Tensor3<Real> J(projected_dim, projected_dim, natural_coord.cols()); parent_element::computeDNDS(natural_coord, dnds); parent_element::computeJMat(dnds, projected_nodal_coord, J); for (UInt p = 0; p < nb_points; ++p) { Matrix<Real> shape_deriv_p = shape_deriv(p); interpolation_element::computeDNDS(natural_coord(p), shape_deriv_p, projected_nodal_coord, n); Matrix<Real> dNdS = shape_deriv_p; Matrix<Real> inv_J(projected_dim, projected_dim); inv_J.inverse(J(p)); shape_deriv_p.mul<false, false>(inv_J, dNdS); } } else { for (UInt p = 0; p < nb_points; ++p) { Matrix<Real> shape_deriv_p = shape_deriv(p); interpolation_element::computeDNDS(natural_coord(p), shape_deriv_p, real_nodal_coord, n); } } } /// compute jacobian (or integration variable change factor) for a given point static inline void computeJacobian(const Matrix<Real> & natural_coords, const Matrix<Real> & nodal_coords, Vector<Real> & jacobians) { parent_element::computeJacobian(natural_coords, nodal_coords, jacobians); } public: static AKANTU_GET_MACRO_NOT_CONST(Kind, _ek_structural, ElementKind); static AKANTU_GET_MACRO_NOT_CONST(P1ElementType, _not_defined, ElementType); static AKANTU_GET_MACRO_NOT_CONST(FacetType, _not_defined, ElementType); static ElementType getFacetType(__attribute__((unused)) UInt t = 0) { return _not_defined; } static AKANTU_GET_MACRO_NOT_CONST( SpatialDimension, ElementClassProperty<element_type>::spatial_dimension, UInt); static ElementType * getFacetTypeInternal() { return NULL; } }; #include "element_classes/element_class_bernoulli_beam_inline_impl.cc" #include "element_classes/element_class_kirchhoff_shell_inline_impl.cc" -__END_AKANTU__ +} // akantu diff --git a/src/fe_engine/element_class_tmpl.hh b/src/fe_engine/element_class_tmpl.hh index 6827f7be8..e6bdc6db1 100644 --- a/src/fe_engine/element_class_tmpl.hh +++ b/src/fe_engine/element_class_tmpl.hh @@ -1,510 +1,510 @@ /** * @file element_class_tmpl.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Thomas Menouillard <tmenouillard@stucky.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Thu Oct 22 2015 * * @brief Implementation of the inline templated function of the element class * descriptions * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "gauss_integration_tmpl.hh" /* -------------------------------------------------------------------------- */ #include <type_traits> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* GeometricalElement */ /* -------------------------------------------------------------------------- */ template <GeometricalType geometrical_type, GeometricalShapeType shape> inline const MatrixProxy<UInt> GeometricalElement<geometrical_type, shape>::getFacetLocalConnectivityPerElement(UInt t) { return MatrixProxy<UInt>(facet_connectivity[t], nb_facets[t], nb_nodes_per_facet[t]); } /* -------------------------------------------------------------------------- */ template <GeometricalType geometrical_type, GeometricalShapeType shape> inline UInt GeometricalElement<geometrical_type, shape>::getNbFacetsPerElement() { UInt total_nb_facets = 0; for (UInt n = 0; n < nb_facet_types; ++n) { total_nb_facets += nb_facets[n]; } return total_nb_facets; } /* -------------------------------------------------------------------------- */ template <GeometricalType geometrical_type, GeometricalShapeType shape> inline UInt GeometricalElement<geometrical_type, shape>::getNbFacetsPerElement(UInt t) { return nb_facets[t]; } /* -------------------------------------------------------------------------- */ template <GeometricalType geometrical_type, GeometricalShapeType shape> template <class vector_type> inline bool GeometricalElement<geometrical_type, shape>::contains( const vector_type & coords) { return GeometricalShapeContains<shape>::contains(coords); } /* -------------------------------------------------------------------------- */ template <> template <class vector_type> inline bool GeometricalShapeContains<_gst_point>::contains(const vector_type & coords) { return (coords(0) < std::numeric_limits<Real>::epsilon()); } /* -------------------------------------------------------------------------- */ template <> template <class vector_type> inline bool GeometricalShapeContains<_gst_square>::contains(const vector_type & coords) { bool in = true; for (UInt i = 0; i < coords.size() && in; ++i) in &= ((coords(i) >= -(1. + std::numeric_limits<Real>::epsilon())) && (coords(i) <= (1. + std::numeric_limits<Real>::epsilon()))); return in; } /* -------------------------------------------------------------------------- */ template <> template <class vector_type> inline bool GeometricalShapeContains<_gst_triangle>::contains(const vector_type & coords) { bool in = true; Real sum = 0; for (UInt i = 0; (i < coords.size()) && in; ++i) { in &= ((coords(i) >= -(Math::getTolerance())) && (coords(i) <= (1. + Math::getTolerance()))); sum += coords(i); } if (in) return (in && (sum <= (1. + Math::getTolerance()))); return in; } /* -------------------------------------------------------------------------- */ template <> template <class vector_type> inline bool GeometricalShapeContains<_gst_prism>::contains(const vector_type & coords) { bool in = ((coords(0) >= -1.) && (coords(0) <= 1.)); // x in segment [-1, 1] // y and z in triangle in &= ((coords(1) >= 0) && (coords(1) <= 1.)); in &= ((coords(2) >= 0) && (coords(2) <= 1.)); Real sum = coords(1) + coords(2); return (in && (sum <= 1)); } /* -------------------------------------------------------------------------- */ /* InterpolationElement */ /* -------------------------------------------------------------------------- */ template <InterpolationType interpolation_type, InterpolationKind kind> inline void InterpolationElement<interpolation_type, kind>::computeShapes( const Matrix<Real> & natural_coord, Matrix<Real> & N) { UInt nb_points = natural_coord.cols(); for (UInt p = 0; p < nb_points; ++p) { Vector<Real> Np(N(p)); Vector<Real> ncoord_p(natural_coord(p)); computeShapes(ncoord_p, Np); } } /* -------------------------------------------------------------------------- */ template <InterpolationType interpolation_type, InterpolationKind kind> inline void InterpolationElement<interpolation_type, kind>::computeDNDS( const Matrix<Real> & natural_coord, Tensor3<Real> & dnds) { UInt nb_points = natural_coord.cols(); for (UInt p = 0; p < nb_points; ++p) { Matrix<Real> dnds_p(dnds(p)); Vector<Real> ncoord_p(natural_coord(p)); computeDNDS(ncoord_p, dnds_p); } } /* -------------------------------------------------------------------------- */ /** * interpolate on a point a field for which values are given on the * node of the element using the shape functions at this interpolation point * * @param nodal_values values of the function per node @f$ f_{ij} = f_{n_i j} *@f$ so it should be a matrix of size nb_nodes_per_element @f$\times@f$ *nb_degree_of_freedom * @param shapes value of shape functions at the interpolation point * @param interpolated interpolated value of f @f$ f_j(\xi) = \sum_i f_{n_i j} *N_i @f$ */ template <InterpolationType interpolation_type, InterpolationKind kind> inline void InterpolationElement<interpolation_type, kind>::interpolate( const Matrix<Real> & nodal_values, const Vector<Real> & shapes, Vector<Real> & interpolated) { Matrix<Real> interpm(interpolated.storage(), nodal_values.rows(), 1); Matrix<Real> shapesm( shapes.storage(), InterpolationPorperty<interpolation_type>::nb_nodes_per_element, 1); interpm.mul<false, false>(nodal_values, shapesm); } /* -------------------------------------------------------------------------- */ /** * interpolate on several points a field for which values are given on the * node of the element using the shape functions at the interpolation point * * @param nodal_values values of the function per node @f$ f_{ij} = f_{n_i j} *@f$ so it should be a matrix of size nb_nodes_per_element @f$\times@f$ *nb_degree_of_freedom * @param shapes value of shape functions at the interpolation point * @param interpolated interpolated values of f @f$ f_j(\xi) = \sum_i f_{n_i j} *N_i @f$ */ template <InterpolationType interpolation_type, InterpolationKind kind> inline void InterpolationElement<interpolation_type, kind>::interpolate( const Matrix<Real> & nodal_values, const Matrix<Real> & shapes, Matrix<Real> & interpolated) { UInt nb_points = shapes.cols(); for (UInt p = 0; p < nb_points; ++p) { Vector<Real> Np(shapes(p)); Vector<Real> interpolated_p(interpolated(p)); interpolate(nodal_values, Np, interpolated_p); } } /* -------------------------------------------------------------------------- */ /** * interpolate the field on a point given in natural coordinates the field which * values are given on the node of the element * * @param natural_coords natural coordinates of point where to interpolate \xi * @param nodal_values values of the function per node @f$ f_{ij} = f_{n_i j} *@f$ so it should be a matrix of size nb_nodes_per_element @f$\times@f$ *nb_degree_of_freedom * @param interpolated interpolated value of f @f$ f_j(\xi) = \sum_i f_{n_i j} *N_i @f$ */ template <InterpolationType interpolation_type, InterpolationKind kind> inline void InterpolationElement<interpolation_type, kind>::interpolateOnNaturalCoordinates( const Vector<Real> & natural_coords, const Matrix<Real> & nodal_values, Vector<Real> & interpolated) { Vector<Real> shapes( InterpolationPorperty<interpolation_type>::nb_nodes_per_element); computeShapes(natural_coords, shapes); interpolate(nodal_values, shapes, interpolated); } /* -------------------------------------------------------------------------- */ /// @f$ gradient_{ij} = \frac{\partial f_j}{\partial s_i} = \sum_k /// \frac{\partial N_k}{\partial s_i}f_{j n_k} @f$ template <InterpolationType interpolation_type, InterpolationKind kind> inline void InterpolationElement<interpolation_type, kind>::gradientOnNaturalCoordinates( const Vector<Real> & natural_coords, const Matrix<Real> & f, Matrix<Real> & gradient) { Matrix<Real> dnds( InterpolationPorperty<interpolation_type>::natural_space_dimension, InterpolationPorperty<interpolation_type>::nb_nodes_per_element); computeDNDS(natural_coords, dnds); gradient.mul<false, true>(f, dnds); } /* -------------------------------------------------------------------------- */ /* ElementClass */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template <ElementType type, ElementKind kind> inline void ElementClass<type, kind>::computeJMat(const Tensor3<Real> & dnds, const Matrix<Real> & node_coords, Tensor3<Real> & J) { UInt nb_points = dnds.size(2); for (UInt p = 0; p < nb_points; ++p) { Matrix<Real> J_p(J(p)); Matrix<Real> dnds_p(dnds(p)); computeJMat(dnds_p, node_coords, J_p); } } /* -------------------------------------------------------------------------- */ template <ElementType type, ElementKind kind> inline void ElementClass<type, kind>::computeJMat(const Matrix<Real> & dnds, const Matrix<Real> & node_coords, Matrix<Real> & J) { /// @f$ J = dxds = dnds * x @f$ J.mul<false, true>(dnds, node_coords); } /* -------------------------------------------------------------------------- */ template <ElementType type, ElementKind kind> inline void ElementClass<type, kind>::computeJacobian(const Matrix<Real> & natural_coords, const Matrix<Real> & node_coords, Vector<Real> & jacobians) { UInt nb_points = natural_coords.cols(); Matrix<Real> dnds(interpolation_property::natural_space_dimension, interpolation_property::nb_nodes_per_element); Matrix<Real> J(natural_coords.rows(), node_coords.rows()); for (UInt p = 0; p < nb_points; ++p) { Vector<Real> ncoord_p(natural_coords(p)); interpolation_element::computeDNDS(ncoord_p, dnds); computeJMat(dnds, node_coords, J); computeJacobian(J, jacobians(p)); } } /* -------------------------------------------------------------------------- */ template <ElementType type, ElementKind kind> inline void ElementClass<type, kind>::computeJacobian(const Tensor3<Real> & J, Vector<Real> & jacobians) { UInt nb_points = J.size(2); for (UInt p = 0; p < nb_points; ++p) { computeJacobian(J(p), jacobians(p)); } } /* -------------------------------------------------------------------------- */ template <ElementType type, ElementKind kind> inline void ElementClass<type, kind>::computeJacobian(const Matrix<Real> & J, Real & jacobians) { if (J.rows() == J.cols()) { jacobians = Math::det<element_property::spatial_dimension>(J.storage()); } else { interpolation_element::computeSpecialJacobian(J, jacobians); } } /* -------------------------------------------------------------------------- */ template <ElementType type, ElementKind kind> inline void ElementClass<type, kind>::computeShapeDerivatives(const Tensor3<Real> & J, const Tensor3<Real> & dnds, Tensor3<Real> & shape_deriv) { UInt nb_points = J.size(2); for (UInt p = 0; p < nb_points; ++p) { Matrix<Real> shape_deriv_p(shape_deriv(p)); computeShapeDerivatives(J(p), dnds(p), shape_deriv_p); } } /* -------------------------------------------------------------------------- */ template <ElementType type, ElementKind kind> inline void ElementClass<type, kind>::computeShapeDerivatives(const Matrix<Real> & J, const Matrix<Real> & dnds, Matrix<Real> & shape_deriv) { Matrix<Real> inv_J(J.rows(), J.cols()); Math::inv<element_property::spatial_dimension>(J.storage(), inv_J.storage()); shape_deriv.mul<false, false>(inv_J, dnds); } /* -------------------------------------------------------------------------- */ template <ElementType type, ElementKind kind> inline void ElementClass<type, kind>::computeNormalsOnNaturalCoordinates( const Matrix<Real> & coord, Matrix<Real> & f, Matrix<Real> & normals) { UInt dimension = normals.rows(); UInt nb_points = coord.cols(); AKANTU_DEBUG_ASSERT((dimension - 1) == interpolation_property::natural_space_dimension, "cannot extract a normal because of dimension mismatch " << dimension - 1 << " " << interpolation_property::natural_space_dimension); Matrix<Real> J(dimension, interpolation_property::natural_space_dimension); for (UInt p = 0; p < nb_points; ++p) { interpolation_element::gradientOnNaturalCoordinates(coord(p), f, J); if (dimension == 2) { Math::normal2(J.storage(), normals(p).storage()); } if (dimension == 3) { Math::normal3(J(0).storage(), J(1).storage(), normals(p).storage()); } } } /* ------------------------------------------------------------------------- */ /** * In the non linear cases we need to iterate to find the natural coordinates *@f$\xi@f$ * provided real coordinates @f$x@f$. * * We want to solve: @f$ x- \phi(\xi) = 0@f$ with @f$\phi(\xi) = \sum_I N_I(\xi) *x_I@f$ * the mapping function which uses the nodal coordinates @f$x_I@f$. * * To that end we use the Newton method and the following series: * * @f$ \frac{\partial \phi(x_k)}{\partial \xi} \left( \xi_{k+1} - \xi_k \right) *= x - \phi(x_k)@f$ * * When we consider elements embedded in a dimension higher than them (2D *triangle in a 3D space for example) * @f$ J = \frac{\partial \phi(\xi_k)}{\partial \xi}@f$ is of dimension *@f$dim_{space} \times dim_{elem}@f$ which * is not invertible in most cases. Rather we can solve the problem: * * @f$ J^T J \left( \xi_{k+1} - \xi_k \right) = J^T \left( x - \phi(\xi_k) *\right) @f$ * * So that * * @f$ d\xi = \xi_{k+1} - \xi_k = (J^T J)^{-1} J^T \left( x - \phi(\xi_k) *\right) @f$ * * So that if the series converges we have: * * @f$ 0 = J^T \left( \phi(\xi_\infty) - x \right) @f$ * * And we see that this is ill-posed only if @f$ J^T x = 0@f$ which means that *the vector provided * is normal to any tangent which means it is outside of the element itself. * * @param real_coords: the real coordinates the natural coordinates are sought *for * @param node_coords: the coordinates of the nodes forming the element * @param natural_coords: output->the sought natural coordinates * @param spatial_dimension: spatial dimension of the problem * **/ template <ElementType type, ElementKind kind> inline void ElementClass<type, kind>::inverseMap( const Vector<Real> & real_coords, const Matrix<Real> & node_coords, Vector<Real> & natural_coords, Real tolerance) { UInt spatial_dimension = real_coords.size(); UInt dimension = natural_coords.size(); // matrix copy of the real_coords Matrix<Real> mreal_coords(real_coords.storage(), spatial_dimension, 1); // initial guess // Matrix<Real> natural_guess(natural_coords.storage(), dimension, 1); natural_coords.clear(); // real space coordinates provided by initial guess Matrix<Real> physical_guess(dimension, 1); // objective function f = real_coords - physical_guess Matrix<Real> f(dimension, 1); // dnds computed on the natural_guess // Matrix<Real> dnds(interpolation_element::nb_nodes_per_element, // spatial_dimension); // J Jacobian matrix computed on the natural_guess Matrix<Real> J(spatial_dimension, dimension); // G = J^t * J Matrix<Real> G(spatial_dimension, spatial_dimension); // Ginv = G^{-1} Matrix<Real> Ginv(spatial_dimension, spatial_dimension); // J = Ginv * J^t Matrix<Real> F(spatial_dimension, dimension); // dxi = \xi_{k+1} - \xi in the iterative process Matrix<Real> dxi(spatial_dimension, 1); /* --------------------------- */ /* init before iteration loop */ /* --------------------------- */ // do interpolation Vector<Real> physical_guess_v(physical_guess.storage(), dimension); interpolation_element::interpolateOnNaturalCoordinates( natural_coords, node_coords, physical_guess_v); // compute initial objective function value f = real_coords - physical_guess f = mreal_coords; f -= physical_guess; // compute initial error Real inverse_map_error = f.norm<L_2>(); /* --------------------------- */ /* iteration loop */ /* --------------------------- */ while (tolerance < inverse_map_error) { // compute J^t interpolation_element::gradientOnNaturalCoordinates(natural_coords, node_coords, J); // compute G G.mul<true, false>(J, J); // inverse G Ginv.inverse(G); // compute F F.mul<false, true>(Ginv, J); // compute increment dxi.mul<false, false>(F, f); // update our guess natural_coords += Vector<Real>(dxi(0)); // interpolate interpolation_element::interpolateOnNaturalCoordinates( natural_coords, node_coords, physical_guess_v); // compute error f = mreal_coords; f -= physical_guess; inverse_map_error = f.norm<L_2>(); } // memcpy(natural_coords.storage(), natural_guess.storage(), sizeof(Real) * // natural_coords.size()); } /* -------------------------------------------------------------------------- */ template <ElementType type, ElementKind kind> inline void ElementClass<type, kind>::inverseMap( const Matrix<Real> & real_coords, const Matrix<Real> & node_coords, Matrix<Real> & natural_coords, Real tolerance) { UInt nb_points = real_coords.cols(); for (UInt p = 0; p < nb_points; ++p) { Vector<Real> X(real_coords(p)); Vector<Real> ncoord_p(natural_coords(p)); inverseMap(X, node_coords, ncoord_p, tolerance); } } -__END_AKANTU__ +} // akantu diff --git a/src/fe_engine/fe_engine.cc b/src/fe_engine/fe_engine.cc index 0b0ca4afa..88ee79e4d 100644 --- a/src/fe_engine/fe_engine.cc +++ b/src/fe_engine/fe_engine.cc @@ -1,85 +1,85 @@ /** * @file fe_engine.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Jul 20 2010 * @date last modification: Fri Dec 11 2015 * * @brief Implementation of the FEEngine class * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "fe_engine.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ FEEngine::FEEngine(Mesh & mesh, UInt element_dimension, ID id, MemoryID memory_id) : Memory(id, memory_id), mesh(mesh), normals_on_integration_points("normals_on_quad_points", id, memory_id) { AKANTU_DEBUG_IN(); this->element_dimension = (element_dimension != _all_dimensions) ? element_dimension : mesh.getSpatialDimension(); init(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEEngine::init() {} /* -------------------------------------------------------------------------- */ FEEngine::~FEEngine() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEEngine::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "FEEngine [" << 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 << "]" << std::endl; } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/fe_engine/fe_engine.hh b/src/fe_engine/fe_engine.hh index 046eab625..4908b104e 100644 --- a/src/fe_engine/fe_engine.hh +++ b/src/fe_engine/fe_engine.hh @@ -1,385 +1,385 @@ /** * @file fe_engine.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 22 2015 * * @brief FEM class * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_FE_ENGINE_HH__ #define __AKANTU_FE_ENGINE_HH__ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" #include "element_type_map.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class Mesh; class Integrator; class ShapeFunctions; class DOFManager; class Element; } /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /** * The generic FEEngine class derived in a FEEngineTemplate class * containing the * shape functions and the integration method */ class FEEngine : protected Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FEEngine(Mesh & mesh, UInt spatial_dimension = _all_dimensions, ID id = "fem", MemoryID memory_id = 0); virtual ~FEEngine(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// pre-compute all the shape functions, their derivatives and the jacobians virtual void initShapeFunctions(const GhostType & ghost_type = _not_ghost) = 0; /// extract the nodal values and store them per element template <typename T> static void extractNodalToElementField( const Mesh & mesh, const Array<T> & nodal_f, Array<T> & elemental_f, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter); /// filter a field template <typename T> static void filterElementalData(const Mesh & mesh, const Array<T> & quad_f, Array<T> & filtered_f, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter); /* ------------------------------------------------------------------------ */ /* Integration method bridges */ /* ------------------------------------------------------------------------ */ /// integrate f for all elements of type "type" virtual void integrate(const Array<Real> & f, Array<Real> & intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const = 0; /// integrate a scalar value f on all elements of type "type" virtual Real integrate(const Array<Real> & f, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const = 0; /// integrate f for all integration points of type "type" but don't sum over /// all integration points virtual void integrateOnIntegrationPoints( const Array<Real> & f, Array<Real> & intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const = 0; /// integrate one element scalar value on all elements of type "type" virtual Real integrate(const Vector<Real> & f, const ElementType & type, UInt index, const GhostType & ghost_type = _not_ghost) const = 0; /* ------------------------------------------------------------------------ */ /* compatibility with old FEEngine fashion */ /* ------------------------------------------------------------------------ */ #ifndef SWIG /// get the number of integration points virtual UInt getNbIntegrationPoints(const ElementType & type, const GhostType & ghost_type = _not_ghost) const = 0; /// get the precomputed shapes const virtual Array<Real> & getShapes(const ElementType & type, const GhostType & ghost_type = _not_ghost, UInt id = 0) const = 0; /// get the derivatives of shapes const virtual Array<Real> & getShapesDerivatives(const ElementType & type, const GhostType & ghost_type = _not_ghost, UInt id = 0) const = 0; /// get integration points const virtual Matrix<Real> & getIntegrationPoints(const ElementType & type, const GhostType & ghost_type = _not_ghost) const = 0; #endif /* ------------------------------------------------------------------------ */ /* Shape method bridges */ /* ------------------------------------------------------------------------ */ /// Compute the gradient nablauq on the integration points of an element type /// from nodal values u virtual void gradientOnIntegrationPoints( const Array<Real> & u, Array<Real> & nablauq, const UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const = 0; /// Interpolate a nodal field u at the integration points of an element type /// -> uq virtual void interpolateOnIntegrationPoints( const Array<Real> & u, Array<Real> & uq, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const = 0; /// Interpolate a nodal field u at the integration points of many element /// types -> uq virtual void interpolateOnIntegrationPoints( const Array<Real> & u, ElementTypeMapArray<Real> & uq, const ElementTypeMapArray<UInt> * filter_elements = NULL) const = 0; /// Compute the interpolation point position in the global coordinates for /// many element types virtual void computeIntegrationPointsCoordinates( ElementTypeMapArray<Real> & integration_points_coordinates, const ElementTypeMapArray<UInt> * filter_elements = NULL) const = 0; /// Compute the interpolation point position in the global coordinates for an /// element type virtual void computeIntegrationPointsCoordinates( Array<Real> & integration_points_coordinates, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const = 0; /// Build pre-computed matrices for interpolation of field form integration /// points at other given positions (interpolation_points) virtual void initElementalFieldInterpolationFromIntegrationPoints( const ElementTypeMapArray<Real> & interpolation_points_coordinates, ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices, ElementTypeMapArray<Real> & integration_points_coordinates_inv_matrices, const ElementTypeMapArray<UInt> * element_filter) const = 0; /// interpolate field at given position (interpolation_points) from given /// values of this field at integration points (field) virtual void interpolateElementalFieldFromIntegrationPoints( const ElementTypeMapArray<Real> & field, const ElementTypeMapArray<Real> & interpolation_points_coordinates, ElementTypeMapArray<Real> & result, const GhostType ghost_type, const ElementTypeMapArray<UInt> * element_filter) const = 0; /// Interpolate field at given position from given values of this field at /// integration points (field) /// using matrices precomputed with /// initElementalFieldInterplationFromIntegrationPoints virtual void interpolateElementalFieldFromIntegrationPoints( const ElementTypeMapArray<Real> & field, const ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices, const ElementTypeMapArray<Real> & integration_points_coordinates_inv_matrices, ElementTypeMapArray<Real> & result, const GhostType ghost_type, const ElementTypeMapArray<UInt> * element_filter) const = 0; /// interpolate on a phyiscal point inside an element virtual void interpolate(const Vector<Real> & real_coords, const Matrix<Real> & nodal_values, Vector<Real> & interpolated, const Element & element) const = 0; /// compute the shape on a provided point virtual void computeShapes(const Vector<Real> & real_coords, UInt elem, const ElementType & type, Vector<Real> & shapes, const GhostType & ghost_type = _not_ghost) const = 0; /// compute the shape derivatives on a provided point virtual void computeShapeDerivatives(const Vector<Real> & real__coords, UInt element, const ElementType & type, Matrix<Real> & shape_derivatives, const GhostType & ghost_type = _not_ghost) const = 0; /* ------------------------------------------------------------------------ */ /* Other methods */ /* ------------------------------------------------------------------------ */ /// pre-compute normals on integration points virtual void computeNormalsOnIntegrationPoints( const GhostType & ghost_type = _not_ghost) = 0; /// pre-compute normals on integration points virtual void computeNormalsOnIntegrationPoints( __attribute__((unused)) const Array<Real> & field, __attribute__((unused)) const GhostType & ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// pre-compute normals on integration points virtual void computeNormalsOnIntegrationPoints( __attribute__((unused)) const Array<Real> & field, __attribute__((unused)) Array<Real> & normal, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type = _not_ghost) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// assemble a field as a lumped matrix (ex. rho in lumped mass) virtual void assembleFieldLumped(__attribute__((unused)) const Array<Real> & field, __attribute__((unused)) const ID & lumped, __attribute__((unused)) const ID & dof_id, __attribute__((unused)) DOFManager & dof_manager, __attribute__((unused)) ElementType type, __attribute__((unused)) const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); }; /// assemble a field as a matrix (ex. rho to mass matrix) virtual void assembleFieldMatrix(__attribute__((unused)) const Array<Real> & field_1, __attribute__((unused)) UInt nb_degree_of_freedom, __attribute__((unused)) SparseMatrix & matrix, __attribute__((unused)) ElementType type, __attribute__((unused)) const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); } #ifdef AKANTU_STRUCTURAL_MECHANICS /// assemble a field as a matrix for structural elements (ex. rho to mass /// matrix) virtual void assembleFieldMatrix( __attribute__((unused)) const Array<Real> & field_1, __attribute__((unused)) UInt nb_degree_of_freedom, __attribute__((unused)) SparseMatrix & M, __attribute__((unused)) Array<Real> * n, __attribute__((unused)) ElementTypeMapArray<Real> & rotation_mat, __attribute__((unused)) ElementType type, __attribute__((unused)) const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute shapes function in a matrix for structural elements virtual void computeShapesMatrix( __attribute__((unused)) const ElementType & type, __attribute__((unused)) UInt nb_degree_of_freedom, __attribute__((unused)) UInt nb_nodes_per_element, __attribute__((unused)) Array<Real> * n, __attribute__((unused)) UInt id, __attribute__((unused)) UInt degree_to_interpolate, __attribute__((unused)) UInt degree_interpolated, __attribute__((unused)) const bool sign, __attribute__((unused)) const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); } #endif /// 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: /// get the dimension of the element handeled by this fe_engine object AKANTU_GET_MACRO(ElementDimension, element_dimension, UInt); /// get the mesh contained in the fem object AKANTU_GET_MACRO(Mesh, mesh, const Mesh &); /// get the mesh contained in the fem object AKANTU_GET_MACRO_NOT_CONST(Mesh, mesh, Mesh &); /// get the in-radius of an element static inline Real getElementInradius(const Matrix<Real> & coord, const ElementType & type); /// get the normals on integration points AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(NormalsOnIntegrationPoints, normals_on_integration_points, Real); /// get cohesive element type for a given facet type static inline ElementType getCohesiveElementType(const ElementType & type_facet); /// get igfem element type for a given regular type static inline Vector<ElementType> getIGFEMElementTypes(const ElementType & type); /// get the interpolation element associated to an element type static inline InterpolationType getInterpolationType(const ElementType & el_type); /// get the shape function class (probably useless: see getShapeFunction in /// fe_engine_template.hh) virtual const ShapeFunctions & getShapeFunctionsInterface() const = 0; /// get the integrator class (probably useless: see getIntegrator in /// fe_engine_template.hh) virtual const Integrator & getIntegratorInterface() const = 0; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// spatial dimension of the problem UInt element_dimension; /// the mesh on which all computation are made Mesh & mesh; /// normals at integration points ElementTypeMapArray<Real> normals_on_integration_points; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const FEEngine & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #include "fe_engine_inline_impl.cc" #include "fe_engine_template.hh" #endif /* __AKANTU_FE_ENGINE_HH__ */ diff --git a/src/fe_engine/fe_engine_inline_impl.cc b/src/fe_engine/fe_engine_inline_impl.cc index 6d33519a5..b70246dc9 100644 --- a/src/fe_engine/fe_engine_inline_impl.cc +++ b/src/fe_engine/fe_engine_inline_impl.cc @@ -1,207 +1,207 @@ /** * @file fe_engine_inline_impl.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Jul 20 2010 * @date last modification: Sat Sep 05 2015 * * @brief Implementation of the inline functions of the FEEngine Class * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "fe_engine.hh" #include "mesh.hh" #include "element_class.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_FE_ENGINE_INLINE_IMPL_CC__ #define __AKANTU_FE_ENGINE_INLINE_IMPL_CC__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ inline Real FEEngine::getElementInradius(const Matrix<Real> & coord, const ElementType & type) { AKANTU_DEBUG_IN(); Real inradius = 0; #define GET_INRADIUS(type) inradius = ElementClass<type>::getInradius(coord); AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_INRADIUS); #undef GET_INRADIUS AKANTU_DEBUG_OUT(); return inradius; } /* -------------------------------------------------------------------------- */ inline InterpolationType FEEngine::getInterpolationType(const ElementType & type) { AKANTU_DEBUG_IN(); InterpolationType itp_type = _itp_not_defined; #define GET_ITP(type) itp_type = ElementClassProperty<type>::interpolation_type; AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_ITP); #undef GET_ITP AKANTU_DEBUG_OUT(); return itp_type; } /* -------------------------------------------------------------------------- */ /// @todo rewrite this function in order to get the cohesive element /// type directly from the facet #if defined(AKANTU_COHESIVE_ELEMENT) inline ElementType FEEngine::getCohesiveElementType(const ElementType & type) { AKANTU_DEBUG_IN(); ElementType ctype; #define GET_COHESIVE_TYPE(type) \ ctype = CohesiveFacetProperty<type>::cohesive_type; AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_COHESIVE_TYPE); #undef GET_COHESIVE_TYPE AKANTU_DEBUG_OUT(); return ctype; } #else inline ElementType FEEngine::getCohesiveElementType(__attribute__((unused)) const ElementType & type_facet) { return _not_defined; } #endif /* -------------------------------------------------------------------------- */ #if defined(AKANTU_IGFEM) -__END_AKANTU__ +} // akantu #include "igfem_helper.hh" -__BEGIN_AKANTU__ +namespace akantu { inline Vector<ElementType> FEEngine::getIGFEMElementTypes(const ElementType & type) { #define GET_IGFEM_ELEMENT_TYPES(type) \ return IGFEMHelper::getIGFEMElementTypes<type>(); AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(GET_IGFEM_ELEMENT_TYPES); #undef GET_IGFEM_ELEMENT_TYPES } #endif /* -------------------------------------------------------------------------- */ template <typename T> void FEEngine::extractNodalToElementField(const Mesh & mesh, const Array<T> & nodal_f, Array<T> & elemental_f, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) { AKANTU_DEBUG_IN(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_degree_of_freedom = nodal_f.getNbComponent(); UInt nb_element = mesh.getNbElement(type, ghost_type); UInt * conn_val = mesh.getConnectivity(type, ghost_type).storage(); if (filter_elements != empty_filter) { nb_element = filter_elements.getSize(); } elemental_f.resize(nb_element); T * nodal_f_val = nodal_f.storage(); T * f_val = elemental_f.storage(); UInt * el_conn; for (UInt el = 0; el < nb_element; ++el) { if (filter_elements != empty_filter) el_conn = conn_val + filter_elements(el) * nb_nodes_per_element; else el_conn = conn_val + el * nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = *(el_conn + n); std::copy(nodal_f_val + node * nb_degree_of_freedom, nodal_f_val + (node + 1) * nb_degree_of_freedom, f_val); f_val += nb_degree_of_freedom; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <typename T> void FEEngine::filterElementalData(const Mesh & mesh, const Array<T> & elem_f, Array<T> & filtered_f, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) { AKANTU_DEBUG_IN(); UInt nb_element = mesh.getNbElement(type, ghost_type); if (nb_element == 0) { filtered_f.resize(0); return; } UInt nb_degree_of_freedom = elem_f.getNbComponent(); UInt nb_data_per_element = elem_f.getSize() / nb_element; if (filter_elements != empty_filter) { nb_element = filter_elements.getSize(); } filtered_f.resize(nb_element * nb_data_per_element); T * elem_f_val = elem_f.storage(); T * f_val = filtered_f.storage(); UInt el_offset; for (UInt el = 0; el < nb_element; ++el) { if (filter_elements != empty_filter) el_offset = filter_elements(el); else el_offset = el; std::copy(elem_f_val + el_offset * nb_data_per_element * nb_degree_of_freedom, elem_f_val + (el_offset + 1) * nb_data_per_element * nb_degree_of_freedom, f_val); f_val += nb_degree_of_freedom * nb_data_per_element; } AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_FE_ENGINE_INLINE_IMPL_CC__ */ diff --git a/src/fe_engine/fe_engine_template.hh b/src/fe_engine/fe_engine_template.hh index e87f95d9e..b5891f36f 100644 --- a/src/fe_engine/fe_engine_template.hh +++ b/src/fe_engine/fe_engine_template.hh @@ -1,368 +1,368 @@ /** * @file fe_engine_template.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Dec 08 2015 * * @brief templated class that calls integration and shape objects * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_FE_ENGINE_TEMPLATE_HH__ #define __AKANTU_FE_ENGINE_TEMPLATE_HH__ /* -------------------------------------------------------------------------- */ #include "fe_engine.hh" #include "integrator.hh" #include "shape_functions.hh" /* -------------------------------------------------------------------------- */ #include <type_traits> /* -------------------------------------------------------------------------- */ namespace akantu { class DOFManager; } -__BEGIN_AKANTU__ +namespace akantu { template <ElementKind> struct AssembleLumpedTemplateHelper; template <ElementKind> struct AssembleFieldMatrixHelper; template <ElementKind, typename> struct AssembleFieldMatrixStructHelper; struct DefaultIntegrationOrderFunctor { template <ElementType type> static inline constexpr int getOrder() { return ElementClassProperty<type>::polynomial_degree; } }; /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind = _ek_regular, class IntegrationOrderFunctor = DefaultIntegrationOrderFunctor> class FEEngineTemplate : public FEEngine { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef I<kind, IntegrationOrderFunctor> Integ; typedef S<kind> Shape; FEEngineTemplate(Mesh & mesh, UInt spatial_dimension = _all_dimensions, ID id = "fem", MemoryID memory_id = 0); virtual ~FEEngineTemplate(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// pre-compute all the shape functions, their derivatives and the jacobians void initShapeFunctions(const GhostType & ghost_type = _not_ghost); void initShapeFunctions(const Array<Real> & nodes, const GhostType & ghost_type = _not_ghost); /* ------------------------------------------------------------------------ */ /* Integration method bridges */ /* ------------------------------------------------------------------------ */ /// integrate f for all elements of type "type" void integrate(const Array<Real> & f, Array<Real> & intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const; /// integrate a scalar value on all elements of type "type" Real integrate(const Array<Real> & f, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const; /// integrate one element scalar value on all elements of type "type" virtual Real integrate(const Vector<Real> & f, const ElementType & type, UInt index, const GhostType & ghost_type = _not_ghost) const; /// integrate partially around an integration point (@f$ intf_q = f_q * J_q * /// w_q @f$) void integrateOnIntegrationPoints( const Array<Real> & f, Array<Real> & intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const; /// interpolate on a phyiscal point inside an element void interpolate(const Vector<Real> & real_coords, const Matrix<Real> & nodal_values, Vector<Real> & interpolated, const Element & element) const; /// get the number of integration points UInt getNbIntegrationPoints(const ElementType & type, const GhostType & ghost_type = _not_ghost) const; /// get shapes precomputed const Array<Real> & getShapes(const ElementType & type, const GhostType & ghost_type = _not_ghost, UInt id = 0) const; /// get the derivatives of shapes const Array<Real> & getShapesDerivatives(const ElementType & type, const GhostType & ghost_type = _not_ghost, UInt id = 0) const; /// get integration points const inline Matrix<Real> & getIntegrationPoints(const ElementType & type, const GhostType & ghost_type = _not_ghost) const; /* ------------------------------------------------------------------------ */ /* Shape method bridges */ /* ------------------------------------------------------------------------ */ /// compute the gradient of a nodal field on the integration points void gradientOnIntegrationPoints( const Array<Real> & u, Array<Real> & nablauq, const UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const; /// interpolate a nodal field on the integration points void interpolateOnIntegrationPoints( const Array<Real> & u, Array<Real> & uq, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const; /// interpolate a nodal field on the integration points given a /// by_element_type void interpolateOnIntegrationPoints( const Array<Real> & u, ElementTypeMapArray<Real> & uq, const ElementTypeMapArray<UInt> * filter_elements = NULL) const; /// compute the position of integration points given by an element_type_map /// from nodes position inline void computeIntegrationPointsCoordinates( ElementTypeMapArray<Real> & quadrature_points_coordinates, const ElementTypeMapArray<UInt> * filter_elements = NULL) const; /// compute the position of integration points from nodes position inline void computeIntegrationPointsCoordinates( Array<Real> & quadrature_points_coordinates, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const; /// interpolate field at given position (interpolation_points) from given /// values of this field at integration points (field) inline void interpolateElementalFieldFromIntegrationPoints( const ElementTypeMapArray<Real> & field, const ElementTypeMapArray<Real> & interpolation_points_coordinates, ElementTypeMapArray<Real> & result, const GhostType ghost_type, const ElementTypeMapArray<UInt> * element_filter) const; /// Interpolate field at given position from given values of this field at /// integration points (field) /// using matrices precomputed with /// initElementalFieldInterplationFromIntegrationPoints inline void interpolateElementalFieldFromIntegrationPoints( const ElementTypeMapArray<Real> & field, const ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices, const ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices, ElementTypeMapArray<Real> & result, const GhostType ghost_type, const ElementTypeMapArray<UInt> * element_filter) const; /// Build pre-computed matrices for interpolation of field form integration /// points at other given positions (interpolation_points) inline void initElementalFieldInterpolationFromIntegrationPoints( const ElementTypeMapArray<Real> & interpolation_points_coordinates, ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices, ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices, const ElementTypeMapArray<UInt> * element_filter = NULL) const; /// find natural coords from real coords provided an element void inverseMap(const Vector<Real> & real_coords, UInt element, const ElementType & type, Vector<Real> & natural_coords, const GhostType & ghost_type = _not_ghost) const; /// return true if the coordinates provided are inside the element, false /// otherwise inline bool contains(const Vector<Real> & real_coords, UInt element, const ElementType & type, const GhostType & ghost_type = _not_ghost) const; /// compute the shape on a provided point inline void computeShapes(const Vector<Real> & real_coords, UInt element, const ElementType & type, Vector<Real> & shapes, const GhostType & ghost_type = _not_ghost) const; /// compute the shape derivatives on a provided point inline void computeShapeDerivatives(const Vector<Real> & real__coords, UInt element, const ElementType & type, Matrix<Real> & shape_derivatives, const GhostType & ghost_type = _not_ghost) const; /* ------------------------------------------------------------------------ */ /* Other methods */ /* ------------------------------------------------------------------------ */ /// pre-compute normals on integration points void computeNormalsOnIntegrationPoints(const GhostType & ghost_type = _not_ghost); void computeNormalsOnIntegrationPoints(const Array<Real> & field, const GhostType & ghost_type = _not_ghost); void computeNormalsOnIntegrationPoints( const Array<Real> & field, Array<Real> & normal, const ElementType & type, const GhostType & ghost_type = _not_ghost) const; template <ElementType type> void computeNormalsOnIntegrationPoints(const Array<Real> & field, Array<Real> & normal, const GhostType & ghost_type) const; /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /// assemble a field as a lumped matrix (ex. rho in lumped mass) void assembleFieldLumped(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, ElementType type, const GhostType & ghost_type = _not_ghost) const; /// assemble a field as a matrix (ex. rho to mass matrix) template <class Functor> void assembleFieldMatrix(Functor field_funct, const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager, ElementType type, const GhostType & ghost_type) const; #ifdef AKANTU_STRUCTURAL_MECHANICS /// assemble a field as a matrix (ex. rho to mass matrix) void assembleFieldMatrix(const Array<Real> & field_1, UInt nb_degree_of_freedom, SparseMatrix & M, Array<Real> * n, ElementTypeMapArray<Real> & rotation_mat, const ElementType & type, const GhostType & ghost_type = _not_ghost) const; /// compute shapes function in a matrix for structural elements void computeShapesMatrix(const ElementType & type, UInt nb_degree_of_freedom, UInt nb_nodes_per_element, Array<Real> * n, UInt id, UInt degree_to_interpolate, UInt degree_interpolated, const bool sign, const GhostType & ghost_type = _not_ghost) const; #endif private: friend struct AssembleLumpedTemplateHelper<kind>; friend struct AssembleFieldMatrixHelper<kind>; friend struct AssembleFieldMatrixStructHelper<kind, void>; /// templated function to compute the scaling to assemble a lumped matrix template <ElementType type> void assembleLumpedTemplate(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const; /// @f$ \tilde{M}_{i} = \sum_j M_{ij} = \sum_j \int \rho \varphi_i \varphi_j /// dV = \int \rho \varphi_i dV @f$ template <ElementType type> void assembleLumpedRowSum(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const; /// @f$ \tilde{M}_{i} = c * M_{ii} = \int_{V_e} \rho dV @f$ template <ElementType type> void assembleLumpedDiagonalScaling(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const; /// assemble a field as a matrix (ex. rho to mass matrix) template <class Functor, ElementType type> void assembleFieldMatrix(Functor field_funct, const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const; #ifdef AKANTU_STRUCTURAL_MECHANICS /// assemble a field as a matrix for structural elements (ex. rho to mass /// matrix) template <ElementType type> void assembleFieldMatrix(const Array<Real> & field_1, UInt nb_degree_of_freedom, SparseMatrix & M, Array<Real> * n, ElementTypeMapArray<Real> & rotation_mat, __attribute__((unused)) const GhostType & ghost_type) const; #endif /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the shape class (probably useless: see getShapeFunction) const ShapeFunctions & getShapeFunctionsInterface() const { return shape_functions; }; /// get the shape class const Shape & getShapeFunctions() const { return shape_functions; }; /// get the integrator class (probably useless: see getIntegrator) const Integrator & getIntegratorInterface() const { return integrator; }; /// get the integrator class const Integ & getIntegrator() const { return integrator; }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: Integ integrator; Shape shape_functions; }; -__END_AKANTU__ +} // akantu /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "fe_engine_template_tmpl.hh" /* -------------------------------------------------------------------------- */ /* Shape Linked specialization */ /* -------------------------------------------------------------------------- */ #if defined(AKANTU_STRUCTURAL_MECHANICS) #include "fe_engine_template_tmpl_struct.hh" #endif /* -------------------------------------------------------------------------- */ /* Shape IGFEM specialization */ /* -------------------------------------------------------------------------- */ #if defined(AKANTU_IGFEM) #include "fe_engine_template_tmpl_igfem.hh" #endif #endif /* __AKANTU_FE_ENGINE_TEMPLATE_HH__ */ diff --git a/src/fe_engine/fe_engine_template_cohesive.cc b/src/fe_engine/fe_engine_template_cohesive.cc index 2d3fce764..eb2ad7c71 100644 --- a/src/fe_engine/fe_engine_template_cohesive.cc +++ b/src/fe_engine/fe_engine_template_cohesive.cc @@ -1,174 +1,174 @@ /** * @file fe_engine_template_cohesive.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Oct 31 2012 * @date last modification: Thu Oct 15 2015 * * @brief Specialization of the FEEngineTemplate for cohesive element * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "fe_engine_template.hh" #include "shape_cohesive.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* compatibility functions */ /* -------------------------------------------------------------------------- */ template <> Real FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive, DefaultIntegrationOrderFunctor>:: integrate(const Array<Real> & f, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { AKANTU_DEBUG_IN(); #ifndef AKANTU_NDEBUG UInt nb_element = mesh.getNbElement(type, ghost_type); if (filter_elements != empty_filter) nb_element = filter_elements.getSize(); UInt nb_quadrature_points = getNbIntegrationPoints(type); AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points, "The vector f(" << f.getID() << ") has not the good size."); AKANTU_DEBUG_ASSERT(f.getNbComponent() == 1, "The vector f(" << f.getID() << ") has not the good number of component."); #endif Real integral = 0.; #define INTEGRATE(type) \ integral = integrator.integrate<type>(f, ghost_type, filter_elements); AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(INTEGRATE); #undef INTEGRATE AKANTU_DEBUG_OUT(); return integral; } /* -------------------------------------------------------------------------- */ template <> void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive, DefaultIntegrationOrderFunctor>:: integrate(const Array<Real> & f, Array<Real> & intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { #ifndef AKANTU_NDEBUG UInt nb_element = mesh.getNbElement(type, ghost_type); if (filter_elements == filter_elements) nb_element = filter_elements.getSize(); UInt nb_quadrature_points = getNbIntegrationPoints(type); AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points, "The vector f(" << f.getID() << " size " << f.getSize() << ") has not the good size (" << nb_element << ")."); AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom, "The vector f(" << f.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT(intf.getNbComponent() == nb_degree_of_freedom, "The vector intf(" << intf.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT(intf.getSize() == nb_element, "The vector intf(" << intf.getID() << ") has not the good size."); #endif #define INTEGRATE(type) \ integrator.integrate<type>(f, intf, nb_degree_of_freedom, ghost_type, \ filter_elements); AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(INTEGRATE); #undef INTEGRATE } /* -------------------------------------------------------------------------- */ template <> void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive, DefaultIntegrationOrderFunctor>:: gradientOnIntegrationPoints(const Array<Real> &, Array<Real> &, const UInt, const ElementType &, const GhostType &, const Array<UInt> &) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ template <> template <> void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive, DefaultIntegrationOrderFunctor>:: computeNormalsOnIntegrationPoints<_cohesive_1d_2>( const Array<Real> &, Array<Real> & normal, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT( mesh.getSpatialDimension() == 1, "Mesh dimension must be 1 to compute normals on 1D cohesive elements!"); const ElementType type = _cohesive_1d_2; const ElementType facet_type = Mesh::getFacetType(type); UInt nb_element = mesh.getConnectivity(type, ghost_type).getSize(); normal.resize(nb_element); Array<Element> & facets = mesh.getMeshFacets().getSubelementToElement(type, ghost_type); Array<std::vector<Element> > & segments = mesh.getMeshFacets().getElementToSubelement(facet_type, ghost_type); Real values[2]; for (UInt elem = 0; elem < nb_element; ++elem) { for (UInt p = 0; p < 2; ++p) { Element f = facets(elem, p); Element seg = segments(f.element)[0]; mesh.getBarycenter(seg.element, seg.type, &(values[p]), seg.ghost_type); } Real difference = values[0] - values[1]; AKANTU_DEBUG_ASSERT(difference != 0., "Error in normal computation for cohesive elements"); normal(elem) = difference / std::abs(difference); } AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu diff --git a/src/fe_engine/fe_engine_template_tmpl.hh b/src/fe_engine/fe_engine_template_tmpl.hh index 11813e4a7..b134a3d4f 100644 --- a/src/fe_engine/fe_engine_template_tmpl.hh +++ b/src/fe_engine/fe_engine_template_tmpl.hh @@ -1,1671 +1,1671 @@ /** * @file fe_engine_template_tmpl.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue Feb 15 2011 * @date last modification: Thu Nov 19 2015 * * @brief Template implementation of FEEngineTemplate * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "dof_manager.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::FEEngineTemplate( Mesh & mesh, UInt spatial_dimension, ID id, MemoryID memory_id) : FEEngine(mesh, spatial_dimension, id, memory_id), integrator(mesh, id, memory_id), shape_functions(mesh, id, memory_id) {} /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::~FEEngineTemplate() {} /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct GradientOnIntegrationPointsHelper { template <class S> static void call(__attribute__((unused)) const S & shape_functions, __attribute__((unused)) Mesh & mesh, __attribute__((unused)) const Array<Real> & u, __attribute__((unused)) Array<Real> & nablauq, __attribute__((unused)) const UInt nb_degree_of_freedom, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type, __attribute__((unused)) const Array<UInt> & filter_elements) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define COMPUTE_GRADIENT(type) \ if (element_dimension == ElementClass<type>::getSpatialDimension()) \ shape_functions.template gradientOnIntegrationPoints<type>( \ u, nablauq, nb_degree_of_freedom, ghost_type, filter_elements); #define AKANTU_SPECIALIZE_GRADIENT_ON_INTEGRATION_POINTS_HELPER(kind) \ template <> struct GradientOnIntegrationPointsHelper<kind> { \ template <class S> \ static void call(const S & shape_functions, Mesh & mesh, \ const Array<Real> & u, Array<Real> & nablauq, \ const UInt nb_degree_of_freedom, \ const ElementType & type, const GhostType & ghost_type, \ const Array<UInt> & filter_elements) { \ UInt element_dimension = mesh.getSpatialDimension(type); \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_GRADIENT, kind); \ } \ }; AKANTU_BOOST_ALL_KIND_LIST( AKANTU_SPECIALIZE_GRADIENT_ON_INTEGRATION_POINTS_HELPER, AKANTU_FE_ENGINE_LIST_GRADIENT_ON_INTEGRATION_POINTS) #undef AKANTU_SPECIALIZE_GRADIENT_ON_INTEGRATION_POINTS_HELPER #undef COMPUTE_GRADIENT template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: gradientOnIntegrationPoints(const Array<Real> & u, Array<Real> & nablauq, const UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { AKANTU_DEBUG_IN(); UInt nb_element = mesh.getNbElement(type, ghost_type); if (filter_elements != empty_filter) nb_element = filter_elements.getSize(); UInt nb_points = shape_functions.getIntegrationPoints(type, ghost_type).cols(); #ifndef AKANTU_NDEBUG UInt element_dimension = mesh.getSpatialDimension(type); AKANTU_DEBUG_ASSERT(u.getSize() == mesh.getNbNodes(), "The vector u(" << u.getID() << ") has not the good size."); AKANTU_DEBUG_ASSERT(u.getNbComponent() == nb_degree_of_freedom, "The vector u(" << u.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT( nablauq.getNbComponent() == nb_degree_of_freedom * element_dimension, "The vector nablauq(" << nablauq.getID() << ") has not the good number of component."); // AKANTU_DEBUG_ASSERT(nablauq.getSize() == nb_element * nb_points, // "The vector nablauq(" << nablauq.getID() // << ") has not the good size."); #endif nablauq.resize(nb_element * nb_points); GradientOnIntegrationPointsHelper<kind>::call( shape_functions, mesh, u, nablauq, nb_degree_of_freedom, type, ghost_type, filter_elements); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::initShapeFunctions( const GhostType & ghost_type) { initShapeFunctions(mesh.getNodes(), ghost_type); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::initShapeFunctions( const Array<Real> & nodes, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); Mesh::type_iterator it = mesh.firstType(element_dimension, ghost_type, kind); Mesh::type_iterator end = mesh.lastType(element_dimension, ghost_type, kind); for (; it != end; ++it) { ElementType type = *it; integrator.initIntegrator(nodes, type, ghost_type); const Matrix<Real> & control_points = getIntegrationPoints(type, ghost_type); shape_functions.initShapeFunctions(nodes, control_points, type, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct IntegrateHelper {}; #define INTEGRATE(type) \ integrator.template integrate<type>(f, intf, nb_degree_of_freedom, \ ghost_type, filter_elements); #define AKANTU_SPECIALIZE_INTEGRATE_HELPER(kind) \ template <> struct IntegrateHelper<kind> { \ template <class I> \ static void call(const I & integrator, const Array<Real> & f, \ Array<Real> & intf, UInt nb_degree_of_freedom, \ const ElementType & type, const GhostType & ghost_type, \ const Array<UInt> & filter_elements) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind); \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_INTEGRATE_HELPER) #undef AKANTU_SPECIALIZE_INTEGRATE_HELPER #undef INTEGRATE template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::integrate( const Array<Real> & f, Array<Real> & intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { UInt nb_element = mesh.getNbElement(type, ghost_type); if (filter_elements != empty_filter) nb_element = filter_elements.getSize(); #ifndef AKANTU_NDEBUG UInt nb_quadrature_points = getNbIntegrationPoints(type); AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points, "The vector f(" << f.getID() << " size " << f.getSize() << ") has not the good size (" << nb_element << ")."); AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom, "The vector f(" << f.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT(intf.getNbComponent() == nb_degree_of_freedom, "The vector intf(" << intf.getID() << ") has not the good number of component."); #endif intf.resize(nb_element); IntegrateHelper<kind>::call(integrator, f, intf, nb_degree_of_freedom, type, ghost_type, filter_elements); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct IntegrateScalarHelper {}; #define INTEGRATE(type) \ integral = \ integrator.template integrate<type>(f, ghost_type, filter_elements); #define AKANTU_SPECIALIZE_INTEGRATE_SCALAR_HELPER(kind) \ template <> struct IntegrateScalarHelper<kind> { \ template <class I> \ static Real call(const I & integrator, const Array<Real> & f, \ const ElementType & type, const GhostType & ghost_type, \ const Array<UInt> & filter_elements) { \ Real integral = 0.; \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind); \ return integral; \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_INTEGRATE_SCALAR_HELPER) #undef AKANTU_SPECIALIZE_INTEGRATE_SCALAR_HELPER #undef INTEGRATE template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> Real FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::integrate( const Array<Real> & f, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { AKANTU_DEBUG_IN(); #ifndef AKANTU_NDEBUG // std::stringstream sstr; sstr << ghost_type; // AKANTU_DEBUG_ASSERT(sstr.str() == nablauq.getTag(), // "The vector " << nablauq.getID() << " is not taged " << // ghost_type); UInt nb_element = mesh.getNbElement(type, ghost_type); if (filter_elements != empty_filter) nb_element = filter_elements.getSize(); UInt nb_quadrature_points = getNbIntegrationPoints(type, ghost_type); AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points, "The vector f(" << f.getID() << ") has not the good size. (" << f.getSize() << "!=" << nb_quadrature_points * nb_element << ")"); AKANTU_DEBUG_ASSERT(f.getNbComponent() == 1, "The vector f(" << f.getID() << ") has not the good number of component."); #endif Real integral = IntegrateScalarHelper<kind>::call( integrator, f, type, ghost_type, filter_elements); AKANTU_DEBUG_OUT(); return integral; } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct IntegrateScalarOnOneElementHelper {}; #define INTEGRATE(type) \ res = integrator.template integrate<type>(f, index, ghost_type); #define AKANTU_SPECIALIZE_INTEGRATE_SCALAR_ON_ONE_ELEMENT_HELPER(kind) \ template <> struct IntegrateScalarOnOneElementHelper<kind> { \ template <class I> \ static Real call(const I & integrator, const Vector<Real> & f, \ const ElementType & type, UInt index, \ const GhostType & ghost_type) { \ Real res = 0.; \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind); \ return res; \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_INTEGRATE_SCALAR_ON_ONE_ELEMENT_HELPER) #undef AKANTU_SPECIALIZE_INTEGRATE_SCALAR_ON_ONE_ELEMENT_HELPER #undef INTEGRATE template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> Real FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::integrate( const Vector<Real> & f, const ElementType & type, UInt index, const GhostType & ghost_type) const { Real res = IntegrateScalarOnOneElementHelper<kind>::call(integrator, f, type, index, ghost_type); return res; } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct IntegrateOnIntegrationPointsHelper {}; #define INTEGRATE(type) \ integrator.template integrateOnIntegrationPoints<type>( \ f, intf, nb_degree_of_freedom, ghost_type, filter_elements); #define AKANTU_SPECIALIZE_INTEGRATE_ON_INTEGRATION_POINTS_HELPER(kind) \ template <> struct IntegrateOnIntegrationPointsHelper<kind> { \ template <class I> \ static void call(const I & integrator, const Array<Real> & f, \ Array<Real> & intf, UInt nb_degree_of_freedom, \ const ElementType & type, const GhostType & ghost_type, \ const Array<UInt> & filter_elements) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind); \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_INTEGRATE_ON_INTEGRATION_POINTS_HELPER) #undef AKANTU_SPECIALIZE_INTEGRATE_ON_INTEGRATION_POINTS_HELPER #undef INTEGRATE template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: integrateOnIntegrationPoints(const Array<Real> & f, Array<Real> & intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { UInt nb_element = mesh.getNbElement(type, ghost_type); if (filter_elements != empty_filter) nb_element = filter_elements.getSize(); UInt nb_quadrature_points = getNbIntegrationPoints(type); #ifndef AKANTU_NDEBUG // std::stringstream sstr; sstr << ghost_type; // AKANTU_DEBUG_ASSERT(sstr.str() == nablauq.getTag(), // "The vector " << nablauq.getID() << " is not taged " << // ghost_type); AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points, "The vector f(" << f.getID() << " size " << f.getSize() << ") has not the good size (" << nb_element << ")."); AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom, "The vector f(" << f.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT(intf.getNbComponent() == nb_degree_of_freedom, "The vector intf(" << intf.getID() << ") has not the good number of component."); #endif intf.resize(nb_element * nb_quadrature_points); IntegrateOnIntegrationPointsHelper<kind>::call(integrator, f, intf, nb_degree_of_freedom, type, ghost_type, filter_elements); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct InterpolateOnIntegrationPointsHelper { template <class S> static void call(__attribute__((unused)) const S & shape_functions, __attribute__((unused)) const Array<Real> & u, __attribute__((unused)) Array<Real> & uq, __attribute__((unused)) const UInt nb_degree_of_freedom, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type, __attribute__((unused)) const Array<UInt> & filter_elements) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define INTERPOLATE(type) \ shape_functions.template interpolateOnIntegrationPoints<type>( \ u, uq, nb_degree_of_freedom, ghost_type, filter_elements); #define AKANTU_SPECIALIZE_INTERPOLATE_ON_INTEGRATION_POINTS_HELPER(kind) \ template <> struct InterpolateOnIntegrationPointsHelper<kind> { \ template <class S> \ static void call(const S & shape_functions, const Array<Real> & u, \ Array<Real> & uq, const UInt nb_degree_of_freedom, \ const ElementType & type, const GhostType & ghost_type, \ const Array<UInt> & filter_elements) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTERPOLATE, kind); \ } \ }; AKANTU_BOOST_ALL_KIND_LIST( AKANTU_SPECIALIZE_INTERPOLATE_ON_INTEGRATION_POINTS_HELPER, AKANTU_FE_ENGINE_LIST_INTERPOLATE_ON_INTEGRATION_POINTS) #undef AKANTU_SPECIALIZE_INTERPOLATE_ON_INTEGRATION_POINTS_HELPER #undef INTERPOLATE template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: interpolateOnIntegrationPoints(const Array<Real> & u, Array<Real> & uq, const UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { AKANTU_DEBUG_IN(); UInt nb_points = shape_functions.getIntegrationPoints(type, ghost_type).cols(); UInt nb_element = mesh.getNbElement(type, ghost_type); if (filter_elements != empty_filter) nb_element = filter_elements.getSize(); #ifndef AKANTU_NDEBUG AKANTU_DEBUG_ASSERT(u.getSize() == mesh.getNbNodes(), "The vector u(" << u.getID() << ") has not the good size."); AKANTU_DEBUG_ASSERT(u.getNbComponent() == nb_degree_of_freedom, "The vector u(" << u.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT(uq.getNbComponent() == nb_degree_of_freedom, "The vector uq(" << uq.getID() << ") has not the good number of component."); #endif uq.resize(nb_element * nb_points); InterpolateOnIntegrationPointsHelper<kind>::call(shape_functions, u, uq, nb_degree_of_freedom, type, ghost_type, filter_elements); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: interpolateOnIntegrationPoints( const Array<Real> & u, ElementTypeMapArray<Real> & uq, const ElementTypeMapArray<UInt> * filter_elements) const { AKANTU_DEBUG_IN(); const Array<UInt> * filter = NULL; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; ElementTypeMapArray<Real>::type_iterator it = uq.firstType(_all_dimensions, ghost_type, kind); ElementTypeMapArray<Real>::type_iterator last = uq.lastType(_all_dimensions, ghost_type, kind); for (; it != last; ++it) { ElementType type = *it; UInt nb_quad_per_element = getNbIntegrationPoints(type, ghost_type); UInt nb_element = 0; if (filter_elements) { filter = &((*filter_elements)(type, ghost_type)); nb_element = filter->getSize(); } else { filter = &empty_filter; nb_element = mesh.getNbElement(type, ghost_type); } UInt nb_tot_quad = nb_quad_per_element * nb_element; Array<Real> & quad = uq(type, ghost_type); quad.resize(nb_tot_quad); interpolateOnIntegrationPoints(u, quad, quad.getNbComponent(), type, ghost_type, *filter); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: computeIntegrationPointsCoordinates( ElementTypeMapArray<Real> & quadrature_points_coordinates, const ElementTypeMapArray<UInt> * filter_elements) const { const Array<Real> & nodes_coordinates = mesh.getNodes(); interpolateOnIntegrationPoints( nodes_coordinates, quadrature_points_coordinates, filter_elements); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: computeIntegrationPointsCoordinates( Array<Real> & quadrature_points_coordinates, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { const Array<Real> & nodes_coordinates = mesh.getNodes(); UInt spatial_dimension = mesh.getSpatialDimension(); interpolateOnIntegrationPoints( nodes_coordinates, quadrature_points_coordinates, spatial_dimension, type, ghost_type, filter_elements); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: initElementalFieldInterpolationFromIntegrationPoints( const ElementTypeMapArray<Real> & interpolation_points_coordinates, ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices, ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices, const ElementTypeMapArray<UInt> * element_filter) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = this->mesh.getSpatialDimension(); ElementTypeMapArray<Real> quadrature_points_coordinates( "quadrature_points_coordinates_for_interpolation", getID(), getMemoryID()); mesh.initElementTypeMapArray(quadrature_points_coordinates, spatial_dimension, spatial_dimension); computeIntegrationPointsCoordinates(quadrature_points_coordinates, element_filter); shape_functions.initElementalFieldInterpolationFromIntegrationPoints( interpolation_points_coordinates, interpolation_points_coordinates_matrices, quad_points_coordinates_inv_matrices, quadrature_points_coordinates, element_filter); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: interpolateElementalFieldFromIntegrationPoints( const ElementTypeMapArray<Real> & field, const ElementTypeMapArray<Real> & interpolation_points_coordinates, ElementTypeMapArray<Real> & result, const GhostType ghost_type, const ElementTypeMapArray<UInt> * element_filter) const { ElementTypeMapArray<Real> interpolation_points_coordinates_matrices( "interpolation_points_coordinates_matrices", id, memory_id); ElementTypeMapArray<Real> quad_points_coordinates_inv_matrices( "quad_points_coordinates_inv_matrices", id, memory_id); initElementalFieldInterpolationFromIntegrationPoints( interpolation_points_coordinates, interpolation_points_coordinates_matrices, quad_points_coordinates_inv_matrices, element_filter); interpolateElementalFieldFromIntegrationPoints( field, interpolation_points_coordinates_matrices, quad_points_coordinates_inv_matrices, result, ghost_type, element_filter); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: interpolateElementalFieldFromIntegrationPoints( const ElementTypeMapArray<Real> & field, const ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices, const ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices, ElementTypeMapArray<Real> & result, const GhostType ghost_type, const ElementTypeMapArray<UInt> * element_filter) const { shape_functions.interpolateElementalFieldFromIntegrationPoints( field, interpolation_points_coordinates_matrices, quad_points_coordinates_inv_matrices, result, ghost_type, element_filter); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct InterpolateHelper { template <class S> static void call(__attribute__((unused)) const S & shape_functions, __attribute__((unused)) const Vector<Real> & real_coords, __attribute__((unused)) UInt elem, __attribute__((unused)) const Matrix<Real> & nodal_values, __attribute__((unused)) Vector<Real> & interpolated, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define INTERPOLATE(type) \ shape_functions.template interpolate<type>( \ real_coords, element, nodal_values, interpolated, ghost_type); #define AKANTU_SPECIALIZE_INTERPOLATE_HELPER(kind) \ template <> struct InterpolateHelper<kind> { \ template <class S> \ static void call(const S & shape_functions, \ const Vector<Real> & real_coords, UInt element, \ const Matrix<Real> & nodal_values, \ Vector<Real> & interpolated, const ElementType & type, \ const GhostType & ghost_type) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTERPOLATE, kind); \ } \ }; AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_INTERPOLATE_HELPER, AKANTU_FE_ENGINE_LIST_INTERPOLATE) #undef AKANTU_SPECIALIZE_INTERPOLATE_HELPER #undef INTERPOLATE template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::interpolate( const Vector<Real> & real_coords, const Matrix<Real> & nodal_values, Vector<Real> & interpolated, const Element & element) const { AKANTU_DEBUG_IN(); InterpolateHelper<kind>::call(shape_functions, real_coords, element.element, nodal_values, interpolated, element.type, element.ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: computeNormalsOnIntegrationPoints(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); computeNormalsOnIntegrationPoints(mesh.getNodes(), ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: computeNormalsOnIntegrationPoints(const Array<Real> & field, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); // Real * coord = mesh.getNodes().storage(); UInt spatial_dimension = mesh.getSpatialDimension(); // allocate the normal arrays Mesh::type_iterator it = mesh.firstType(element_dimension, ghost_type, kind); Mesh::type_iterator end = mesh.lastType(element_dimension, ghost_type, kind); for (; it != end; ++it) { ElementType type = *it; UInt size = mesh.getNbElement(type, ghost_type); if (normals_on_integration_points.exists(type, ghost_type)) { normals_on_integration_points(type, ghost_type).resize(size); } else { normals_on_integration_points.alloc(size, spatial_dimension, type, ghost_type); } } // loop over the type to build the normals it = mesh.firstType(element_dimension, ghost_type, kind); for (; it != end; ++it) { Array<Real> & normals_on_quad = normals_on_integration_points(*it, ghost_type); computeNormalsOnIntegrationPoints(field, normals_on_quad, *it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct ComputeNormalsOnIntegrationPoints { template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind k, class IOF> static void call(__attribute__((unused)) const FEEngineTemplate<I, S, k, IOF> & fem, __attribute__((unused)) const Array<Real> & field, __attribute__((unused)) Array<Real> & normal, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define COMPUTE_NORMALS_ON_INTEGRATION_POINTS(type) \ fem.template computeNormalsOnIntegrationPoints<type>(field, normal, \ ghost_type); #define AKANTU_SPECIALIZE_COMPUTE_NORMALS_ON_INTEGRATION_POINTS(kind) \ template <> struct ComputeNormalsOnIntegrationPoints<kind> { \ template <template <ElementKind, class> class I, \ template <ElementKind> class S, ElementKind k, class IOF> \ static void call(const FEEngineTemplate<I, S, k, IOF> & fem, \ const Array<Real> & field, Array<Real> & normal, \ const ElementType & type, const GhostType & ghost_type) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_NORMALS_ON_INTEGRATION_POINTS, \ kind); \ } \ }; AKANTU_BOOST_ALL_KIND_LIST( AKANTU_SPECIALIZE_COMPUTE_NORMALS_ON_INTEGRATION_POINTS, AKANTU_FE_ENGINE_LIST_COMPUTE_NORMALS_ON_INTEGRATION_POINTS) #undef AKANTU_SPECIALIZE_COMPUTE_NORMALS_ON_INTEGRATION_POINTS #undef COMPUTE_NORMALS_ON_INTEGRATION_POINTS template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: computeNormalsOnIntegrationPoints(const Array<Real> & field, Array<Real> & normal, const ElementType & type, const GhostType & ghost_type) const { ComputeNormalsOnIntegrationPoints<kind>::call(*this, field, normal, type, ghost_type); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: computeNormalsOnIntegrationPoints(const Array<Real> & field, Array<Real> & normal, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_points = getNbIntegrationPoints(type, ghost_type); UInt nb_element = mesh.getConnectivity(type, ghost_type).getSize(); normal.resize(nb_element * nb_points); Array<Real>::matrix_iterator normals_on_quad = normal.begin_reinterpret(spatial_dimension, nb_points, nb_element); Array<Real> f_el(0, spatial_dimension * nb_nodes_per_element); FEEngine::extractNodalToElementField(mesh, field, f_el, type, ghost_type); const Matrix<Real> & quads = integrator.template getIntegrationPoints<type>(ghost_type); Array<Real>::matrix_iterator f_it = f_el.begin(spatial_dimension, nb_nodes_per_element); for (UInt elem = 0; elem < nb_element; ++elem) { ElementClass<type>::computeNormalsOnNaturalCoordinates(quads, *f_it, *normals_on_quad); ++normals_on_quad; ++f_it; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* Matrix lumping functions */ /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct AssembleLumpedTemplateHelper {}; #define ASSEMBLE_LUMPED(type) \ fem.template assembleLumpedTemplate<type>(field_1, lumped, dof_id, \ dof_manager, ghost_type) #define AKANTU_SPECIALIZE_ASSEMBLE_HELPER(kind) \ template <> struct AssembleLumpedTemplateHelper<kind> { \ template <template <ElementKind, class> class I, \ template <ElementKind> class S, ElementKind k, class IOF> \ static void call(const FEEngineTemplate<I, S, k, IOF> & fem, \ const Array<Real> & field_1, const ID & lumped, \ const ID & dof_id, DOFManager & dof_manager, \ ElementType type, const GhostType & ghost_type) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(ASSEMBLE_LUMPED, kind); \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_ASSEMBLE_HELPER) #undef AKANTU_SPECIALIZE_ASSEMBLE_HELPER #undef ASSEMBLE_LUMPED /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IOF> void FEEngineTemplate<I, S, kind, IOF>::assembleFieldLumped( const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, ElementType type, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); AssembleLumpedTemplateHelper<kind>::call(*this, field, lumped, dof_id, dof_manager, type, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct AssembleFieldMatrixHelper {}; #define ASSEMBLE_MATRIX(type) \ fem.template assembleFieldMatrix<Functor, type>( \ field_funct, matrix_id, dof_id, dof_manager, ghost_type) #define AKANTU_SPECIALIZE_ASSEMBLE_FIELD_MATRIX_HELPER(kind) \ template <> struct AssembleFieldMatrixHelper<kind> { \ template <template <ElementKind, class> class I, \ template <ElementKind> class S, ElementKind k, class IOF, \ class Functor> \ static void call(const FEEngineTemplate<I, S, k, IOF> & fem, \ Functor field_funct, const ID & matrix_id, \ const ID & dof_id, DOFManager & dof_manager, \ ElementType type, const GhostType & ghost_type) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(ASSEMBLE_MATRIX, kind); \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_ASSEMBLE_FIELD_MATRIX_HELPER) #undef AKANTU_SPECIALIZE_ASSEMBLE_FIELD_MATRIX_HELPER #undef ASSEMBLE_MATRIX template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IOF> template <class Functor> void FEEngineTemplate<I, S, kind, IOF>::assembleFieldMatrix( Functor field_funct, const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager, ElementType type, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); AssembleFieldMatrixHelper<kind>::template call( *this, field_funct, matrix_id, dof_id, dof_manager, type, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: assembleLumpedTemplate(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); this->template assembleLumpedRowSum<type>(field, lumped, dof_id, dof_manager, ghost_type); 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 <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: assembleLumpedRowSum(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt shapes_size = ElementClass<type>::getShapeSize(); UInt nb_degree_of_freedom = field.getNbComponent(); Array<Real> * field_times_shapes = new Array<Real>(0, shapes_size * nb_degree_of_freedom); shape_functions.template fieldTimesShapes<type>(field, *field_times_shapes, ghost_type); UInt nb_element = mesh.getNbElement(type, ghost_type); Array<Real> * int_field_times_shapes = new Array<Real>( nb_element, shapes_size * nb_degree_of_freedom, "inte_rho_x_shapes"); integrator.template integrate<type>( *field_times_shapes, *int_field_times_shapes, nb_degree_of_freedom * shapes_size, ghost_type, empty_filter); delete field_times_shapes; dof_manager.assembleElementalArrayToLumpedMatrix( dof_id, *int_field_times_shapes, lumped, 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 <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: assembleLumpedDiagonalScaling(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); const ElementType & type_p1 = ElementClass<type>::getP1ElementType(); UInt nb_nodes_per_element_p1 = Mesh::getNbNodesPerElement(type_p1); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = integrator.template getIntegrationPoints<type>(ghost_type).cols(); UInt nb_degree_of_freedom = field.getNbComponent(); UInt nb_element = field.getSize() / nb_quadrature_points; Vector<Real> nodal_factor(nb_nodes_per_element); #define ASSIGN_WEIGHT_TO_NODES(corner, mid) \ { \ for (UInt n = 0; n < nb_nodes_per_element_p1; n++) \ nodal_factor(n) = corner; \ for (UInt n = nb_nodes_per_element_p1; n < nb_nodes_per_element; n++) \ nodal_factor(n) = mid; \ } if (type == _triangle_6) ASSIGN_WEIGHT_TO_NODES(1. / 12., 1. / 4.); if (type == _tetrahedron_10) ASSIGN_WEIGHT_TO_NODES(1. / 32., 7. / 48.); if (type == _quadrangle_8) ASSIGN_WEIGHT_TO_NODES( 3. / 76., 16. / 76.); /** coeff. derived by scaling * the diagonal terms of the corresponding * consistent mass computed with 3x3 gauss points; * coeff. are (1./36., 8./36.) for 2x2 gauss points */ if (type == _hexahedron_20) ASSIGN_WEIGHT_TO_NODES( 7. / 248., 16. / 248.); /** coeff. derived by scaling * the diagonal terms of the corresponding * consistent mass computed with 3x3x3 gauss points; * coeff. are (1./40., * 1./15.) for 2x2x2 gauss points */ if (type == _pentahedron_15) { // coefficients derived by scaling the diagonal terms of the corresponding // consistent mass computed with 8 gauss points; for (UInt n = 0; n < nb_nodes_per_element_p1; n++) nodal_factor(n) = 51. / 2358.; Real mid_triangle = 192. / 2358.; Real mid_quadrangle = 300. / 2358.; nodal_factor(6) = mid_triangle; nodal_factor(7) = mid_triangle; nodal_factor(8) = mid_triangle; nodal_factor(9) = mid_quadrangle; nodal_factor(10) = mid_quadrangle; nodal_factor(11) = mid_quadrangle; nodal_factor(12) = mid_triangle; nodal_factor(13) = mid_triangle; nodal_factor(14) = mid_triangle; } if (nb_element == 0) { AKANTU_DEBUG_OUT(); return; } #undef ASSIGN_WEIGHT_TO_NODES /// compute @f$ \int \rho dV = \rho V @f$ for each element Array<Real> * int_field = new Array<Real>(field.getSize(), nb_degree_of_freedom, "inte_rho_x"); integrator.template integrate<type>(field, *int_field, nb_degree_of_freedom, ghost_type, empty_filter); /// distribute the mass of the element to the nodes Array<Real> * lumped_per_node = new Array<Real>( nb_element, nb_degree_of_freedom * nb_nodes_per_element, "mass_per_node"); Array<Real>::const_vector_iterator int_field_it = int_field->begin(nb_degree_of_freedom); Array<Real>::matrix_iterator lumped_per_node_it = lumped_per_node->begin(nb_degree_of_freedom, nb_nodes_per_element); for (UInt e = 0; e < nb_element; ++e) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { Vector<Real> l = (*lumped_per_node_it)(n); l = *int_field_it; l *= nodal_factor(n); } ++int_field_it; ++lumped_per_node_it; } delete int_field; dof_manager.assembleElementalArrayToLumpedMatrix(dof_id, *lumped_per_node, lumped, 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 <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> template <class Functor, ElementType type> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::assembleFieldMatrix( Functor field_funct, const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt shapes_size = ElementClass<type>::getShapeSize(); UInt nb_degree_of_freedom = dof_manager.getDOFs(dof_id).getNbComponent(); UInt lmat_size = nb_degree_of_freedom * shapes_size; UInt nb_element = mesh.getNbElement(type, ghost_type); // \int N * N so degree 2 * degree of N const UInt polynomial_degree = 2 * ElementClassProperty<type>::polynomial_degree; Matrix<Real> integration_points = integrator.template getIntegrationPoints<type, polynomial_degree>(); UInt nb_integration_points = integration_points.cols(); UInt vect_size = nb_integration_points * nb_element; Array<Real> shapes(0, shapes_size); shape_functions.template computeShapesOnIntegrationPoints<type>( mesh.getNodes(), integration_points, shapes, ghost_type); Array<Real> integration_points_pos(vect_size, mesh.getSpatialDimension()); shape_functions.template interpolateOnIntegrationPoints<type>( mesh.getNodes(), integration_points_pos, mesh.getSpatialDimension(), shapes, ghost_type, empty_filter); Array<Real> * modified_shapes = new Array<Real>(vect_size, lmat_size * nb_degree_of_freedom); modified_shapes->clear(); Array<Real> * local_mat = new Array<Real>(vect_size, lmat_size * lmat_size); Array<Real>::matrix_iterator mshapes_it = modified_shapes->begin(nb_degree_of_freedom, lmat_size); Array<Real>::const_vector_iterator shapes_it = shapes.begin(shapes_size); for (UInt q = 0; q < vect_size; ++q, ++mshapes_it, ++shapes_it) { for (UInt d = 0; d < nb_degree_of_freedom; ++d) { for (UInt s = 0; s < shapes_size; ++s) { (*mshapes_it)(d, s * nb_degree_of_freedom + d) = (*shapes_it)(s); } } } Array<Real> field(vect_size, nb_degree_of_freedom); Array<Real>::matrix_iterator field_c_it = field.begin_reinterpret( nb_degree_of_freedom, nb_integration_points, nb_element); Array<Real>::const_matrix_iterator pos_it = integration_points_pos.begin_reinterpret( mesh.getSpatialDimension(), nb_integration_points, nb_element); Element el; el.type = type, el.ghost_type = ghost_type; for (el.element = 0; el.element < nb_element; ++el.element, ++field_c_it, ++pos_it) { field_funct(*field_c_it, el, *pos_it); } mshapes_it = modified_shapes->begin(nb_degree_of_freedom, lmat_size); Array<Real>::matrix_iterator lmat = local_mat->begin(lmat_size, lmat_size); Array<Real>::const_vector_iterator field_it = field.begin_reinterpret(nb_degree_of_freedom, field.getSize()); for (UInt q = 0; q < vect_size; ++q, ++lmat, ++mshapes_it, ++field_it) { const Vector<Real> & rho = *field_it; const Matrix<Real> & N = *mshapes_it; Matrix<Real> & mat = *lmat; Matrix<Real> Nt = N.transpose(); for (UInt d = 0; d < Nt.cols(); ++d) { Nt(d) *= rho(d); } mat.mul<false, false>(Nt, N); } delete modified_shapes; Array<Real> * int_field_times_shapes = new Array<Real>(nb_element, lmat_size * lmat_size, "inte_rho_x_shapes"); this->integrator.template integrate<type, polynomial_degree>( *local_mat, *int_field_times_shapes, lmat_size * lmat_size, ghost_type); delete local_mat; dof_manager.assembleElementalMatricesToMatrix( matrix_id, dof_id, *int_field_times_shapes, type, ghost_type); delete int_field_times_shapes; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct InverseMapHelper { template <class S> static void call(__attribute__((unused)) const S & shape_functions, __attribute__((unused)) const Vector<Real> & real_coords, __attribute__((unused)) UInt element, __attribute__((unused)) const ElementType & type, __attribute__((unused)) Vector<Real> & natural_coords, __attribute__((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define INVERSE_MAP(type) \ shape_functions.template inverseMap<type>(real_coords, element, \ natural_coords, ghost_type); #define AKANTU_SPECIALIZE_INVERSE_MAP_HELPER(kind) \ template <> struct InverseMapHelper<kind> { \ template <class S> \ static void call(const S & shape_functions, \ const Vector<Real> & real_coords, UInt element, \ const ElementType & type, Vector<Real> & natural_coords, \ const GhostType & ghost_type) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(INVERSE_MAP, kind); \ } \ }; AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_INVERSE_MAP_HELPER, AKANTU_FE_ENGINE_LIST_INVERSE_MAP) #undef AKANTU_SPECIALIZE_INVERSE_MAP_HELPER #undef INVERSE_MAP template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::inverseMap( const Vector<Real> & real_coords, UInt element, const ElementType & type, Vector<Real> & natural_coords, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); InverseMapHelper<kind>::call(shape_functions, real_coords, element, type, natural_coords, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct ContainsHelper { template <class S> static void call(__attribute__((unused)) const S & shape_functions, __attribute__((unused)) const Vector<Real> & real_coords, __attribute__((unused)) UInt element, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define CONTAINS(type) \ contain = shape_functions.template contains<type>(real_coords, element, \ ghost_type); #define AKANTU_SPECIALIZE_CONTAINS_HELPER(kind) \ template <> struct ContainsHelper<kind> { \ template <template <ElementKind> class S, ElementKind k> \ static bool call(const S<k> & shape_functions, \ const Vector<Real> & real_coords, UInt element, \ const ElementType & type, const GhostType & ghost_type) { \ bool contain = false; \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(CONTAINS, kind); \ return contain; \ } \ }; AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_CONTAINS_HELPER, AKANTU_FE_ENGINE_LIST_CONTAINS) #undef AKANTU_SPECIALIZE_CONTAINS_HELPER #undef CONTAINS template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline bool FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::contains( const Vector<Real> & real_coords, UInt element, const ElementType & type, const GhostType & ghost_type) const { return ContainsHelper<kind>::call(shape_functions, real_coords, element, type, ghost_type); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct ComputeShapesHelper { template <class S> static void call(__attribute__((unused)) const S & shape_functions, __attribute__((unused)) const Vector<Real> & real_coords, __attribute__((unused)) UInt element, __attribute__((unused)) const ElementType type, __attribute__((unused)) Vector<Real> & shapes, __attribute__((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define COMPUTE_SHAPES(type) \ shape_functions.template computeShapes<type>(real_coords, element, shapes, \ ghost_type); #define AKANTU_SPECIALIZE_COMPUTE_SHAPES_HELPER(kind) \ template <> struct ComputeShapesHelper<kind> { \ template <class S> \ static void call(const S & shape_functions, \ const Vector<Real> & real_coords, UInt element, \ const ElementType type, Vector<Real> & shapes, \ const GhostType & ghost_type) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_SHAPES, kind); \ } \ }; AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_COMPUTE_SHAPES_HELPER, AKANTU_FE_ENGINE_LIST_COMPUTE_SHAPES) #undef AKANTU_SPECIALIZE_COMPUTE_SHAPES_HELPER #undef COMPUTE_SHAPES template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeShapes( const Vector<Real> & real_coords, UInt element, const ElementType & type, Vector<Real> & shapes, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); ComputeShapesHelper<kind>::call(shape_functions, real_coords, element, type, shapes, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct ComputeShapeDerivativesHelper { template <class S> static void call(__attribute__((unused)) const S & shape_functions, __attribute__((unused)) const Vector<Real> & real_coords, __attribute__((unused)) UInt element, __attribute__((unused)) const ElementType type, __attribute__((unused)) Matrix<Real> & shape_derivatives, __attribute__((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define COMPUTE_SHAPE_DERIVATIVES(type) \ Matrix<Real> coords_mat(real_coords.storage(), shape_derivatives.rows(), 1); \ Tensor3<Real> shapesd_tensor(shape_derivatives.storage(), \ shape_derivatives.rows(), \ shape_derivatives.cols(), 1); \ shape_functions.template computeShapeDerivatives<type>( \ coords_mat, element, shapesd_tensor, ghost_type); #define AKANTU_SPECIALIZE_COMPUTE_SHAPE_DERIVATIVES_HELPER(kind) \ template <> struct ComputeShapeDerivativesHelper<kind> { \ template <class S> \ static void call(const S & shape_functions, \ const Vector<Real> & real_coords, UInt element, \ const ElementType type, Matrix<Real> & shape_derivatives, \ const GhostType & ghost_type) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_SHAPE_DERIVATIVES, kind); \ } \ }; AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_COMPUTE_SHAPE_DERIVATIVES_HELPER, AKANTU_FE_ENGINE_LIST_COMPUTE_SHAPES_DERIVATIVES) #undef AKANTU_SPECIALIZE_COMPUTE_SHAPE_DERIVATIVES_HELPER #undef COMPUTE_SHAPE_DERIVATIVES template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeShapeDerivatives( const Vector<Real> & real_coords, UInt element, const ElementType & type, Matrix<Real> & shape_derivatives, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); ComputeShapeDerivativesHelper<kind>::call(shape_functions, real_coords, element, type, shape_derivatives, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct GetNbIntegrationPointsHelper {}; #define GET_NB_INTEGRATION_POINTS(type) \ nb_quad_points = integrator.template getNbIntegrationPoints<type>(ghost_type); #define AKANTU_SPECIALIZE_GET_NB_INTEGRATION_POINTS_HELPER(kind) \ template <> struct GetNbIntegrationPointsHelper<kind> { \ template <template <ElementKind, class> class I, ElementKind k, class IOF> \ static UInt call(const I<k, IOF> & integrator, const ElementType type, \ const GhostType & ghost_type) { \ UInt nb_quad_points = 0; \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_NB_INTEGRATION_POINTS, kind); \ return nb_quad_points; \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_GET_NB_INTEGRATION_POINTS_HELPER) #undef AKANTU_SPECIALIZE_GET_NB_INTEGRATION_POINTS_HELPER #undef GET_NB_INTEGRATION template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline UInt FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getNbIntegrationPoints( const ElementType & type, const GhostType & ghost_type) const { return GetNbIntegrationPointsHelper<kind>::call(integrator, type, ghost_type); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct GetShapesHelper {}; #define GET_SHAPES(type) ret = &(shape_functions.getShapes(type, ghost_type)); #define AKANTU_SPECIALIZE_GET_SHAPES_HELPER(kind) \ template <> struct GetShapesHelper<kind> { \ template <class S> \ static const Array<Real> & call(const S & shape_functions, \ const ElementType type, \ const GhostType & ghost_type) { \ const Array<Real> * ret = NULL; \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_SHAPES, kind); \ return *ret; \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_GET_SHAPES_HELPER) #undef AKANTU_SPECIALIZE_GET_SHAPES_HELPER #undef GET_SHAPES template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline const Array<Real> & FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getShapes( const ElementType & type, const GhostType & ghost_type, __attribute__((unused)) UInt id) const { return GetShapesHelper<kind>::call(shape_functions, type, ghost_type); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct GetShapesDerivativesHelper { template <template <ElementKind> class S, ElementKind k> static const Array<Real> & call(__attribute__((unused)) const S<k> & shape_functions, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type, __attribute__((unused)) UInt id) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define GET_SHAPES_DERIVATIVES(type) \ ret = &(shape_functions.getShapesDerivatives(type, ghost_type)); #define AKANTU_SPECIALIZE_GET_SHAPES_DERIVATIVES_HELPER(kind) \ template <> struct GetShapesDerivativesHelper<kind> { \ template <template <ElementKind> class S, ElementKind k> \ static const Array<Real> & \ call(const S<k> & shape_functions, const ElementType type, \ const GhostType & ghost_type, __attribute__((unused)) UInt id) { \ const Array<Real> * ret = NULL; \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_SHAPES_DERIVATIVES, kind); \ return *ret; \ } \ }; AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_GET_SHAPES_DERIVATIVES_HELPER, AKANTU_FE_ENGINE_LIST_GET_SHAPES_DERIVATIVES) #undef AKANTU_SPECIALIZE_GET_SHAPE_DERIVATIVES_HELPER #undef GET_SHAPES_DERIVATIVES template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline const Array<Real> & FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getShapesDerivatives( const ElementType & type, const GhostType & ghost_type, __attribute__((unused)) UInt id) const { return GetShapesDerivativesHelper<kind>::call(shape_functions, type, ghost_type, id); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct GetIntegrationPointsHelper {}; #define GET_INTEGRATION_POINTS(type) \ ret = &(integrator.template getIntegrationPoints<type>(ghost_type)); #define AKANTU_SPECIALIZE_GET_INTEGRATION_POINTS_HELPER(kind) \ template <> struct GetIntegrationPointsHelper<kind> { \ template <template <ElementKind, class> class I, ElementKind k, class IOF> \ static const Matrix<Real> & call(const I<k, IOF> & integrator, \ const ElementType type, \ const GhostType & ghost_type) { \ const Matrix<Real> * ret = NULL; \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_INTEGRATION_POINTS, kind); \ return *ret; \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_GET_INTEGRATION_POINTS_HELPER) #undef AKANTU_SPECIALIZE_GET_INTEGRATION_POINTS_HELPER #undef GET_INTEGRATION_POINTS template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline const Matrix<Real> & FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getIntegrationPoints( const ElementType & type, const GhostType & ghost_type) const { return GetIntegrationPointsHelper<kind>::call(integrator, type, ghost_type); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::printself( std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "FEEngineTemplate [" << std::endl; stream << space << " + parent [" << std::endl; FEEngine::printself(stream, indent + 3); stream << space << " ]" << std::endl; stream << space << " + shape functions [" << std::endl; shape_functions.printself(stream, indent + 3); stream << space << " ]" << std::endl; stream << space << " + integrator [" << std::endl; integrator.printself(stream, indent + 3); stream << space << " ]" << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #include "integrator_gauss.hh" #include "shape_lagrange.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <> template <> inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular>:: assembleLumpedTemplate<_triangle_6>(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { assembleLumpedDiagonalScaling<_triangle_6>(field, lumped, dof_id, dof_manager, ghost_type); } /* -------------------------------------------------------------------------- */ template <> template <> inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular, DefaultIntegrationOrderFunctor>:: assembleLumpedTemplate<_tetrahedron_10>( const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { assembleLumpedDiagonalScaling<_tetrahedron_10>(field, lumped, dof_id, dof_manager, ghost_type); } /* -------------------------------------------------------------------------- */ template <> template <> inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular>:: assembleLumpedTemplate<_quadrangle_8>(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { assembleLumpedDiagonalScaling<_quadrangle_8>(field, lumped, dof_id, dof_manager, ghost_type); } /* -------------------------------------------------------------------------- */ template <> template <> inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular>:: assembleLumpedTemplate<_hexahedron_20>(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { assembleLumpedDiagonalScaling<_hexahedron_20>(field, lumped, dof_id, dof_manager, ghost_type); } /* -------------------------------------------------------------------------- */ template <> template <> inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular, DefaultIntegrationOrderFunctor>:: assembleLumpedTemplate<_pentahedron_15>( const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { assembleLumpedDiagonalScaling<_pentahedron_15>(field, lumped, dof_id, dof_manager, ghost_type); } /* -------------------------------------------------------------------------- */ template <> template <> inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular, DefaultIntegrationOrderFunctor>:: computeNormalsOnIntegrationPoints<_point_1>( const Array<Real> &, Array<Real> & normal, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(mesh.getSpatialDimension() == 1, "Mesh dimension must be 1 to compute normals on points!"); const ElementType type = _point_1; UInt spatial_dimension = mesh.getSpatialDimension(); // UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_points = getNbIntegrationPoints(type, ghost_type); UInt nb_element = mesh.getConnectivity(type, ghost_type).getSize(); normal.resize(nb_element * nb_points); Array<Real>::matrix_iterator normals_on_quad = normal.begin_reinterpret(spatial_dimension, nb_points, nb_element); const Array<std::vector<Element>> & segments = mesh.getElementToSubelement(type, ghost_type); const Array<Real> & coords = mesh.getNodes(); const Mesh * mesh_segment; if (mesh.isMeshFacets()) mesh_segment = &(mesh.getMeshParent()); else mesh_segment = &mesh; for (UInt elem = 0; elem < nb_element; ++elem) { UInt nb_segment = segments(elem).size(); AKANTU_DEBUG_ASSERT( nb_segment > 0, "Impossible to compute a normal on a point connected to 0 segments"); Real normal_value = 1; if (nb_segment == 1) { const Element & segment = segments(elem)[0]; const Array<UInt> & segment_connectivity = mesh_segment->getConnectivity(segment.type, segment.ghost_type); // const Vector<UInt> & segment_points = // segment_connectivity.begin(Mesh::getNbNodesPerElement(segment.type))[segment.element]; Real difference; if (segment_connectivity(0) == elem) { difference = coords(elem) - coords(segment_connectivity(1)); } else { difference = coords(elem) - coords(segment_connectivity(0)); } normal_value = difference / std::abs(difference); } for (UInt n(0); n < nb_points; ++n) { (*normals_on_quad)(0, n) = normal_value; } ++normals_on_quad; } AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu diff --git a/src/fe_engine/fe_engine_template_tmpl_struct.hh b/src/fe_engine/fe_engine_template_tmpl_struct.hh index 2d21759a3..3f1396218 100644 --- a/src/fe_engine/fe_engine_template_tmpl_struct.hh +++ b/src/fe_engine/fe_engine_template_tmpl_struct.hh @@ -1,246 +1,246 @@ /** * @file fe_engine_template_tmpl_struct.hh * * @author Fabian Barras <fabian.barras@epfl.ch> * @author Sébastien Hartmann <sebastien.hartmann@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Jul 07 2014 * @date last modification: Thu Oct 15 2015 * * @brief Template implementation of FEEngineTemplate for Structural Element * Kinds * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "shape_linked.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <> inline const Array<Real> & FEEngineTemplate<IntegratorGauss, ShapeLinked, _ek_structural, DefaultIntegrationOrderFunctor>:: getShapesDerivatives(const ElementType & type, const GhostType & ghost_type, UInt id) const { AKANTU_DEBUG_IN(); const Array<Real> * ret = NULL; #define GET_SHAPES(type) \ ret = &(shape_functions.getShapesDerivatives(type, ghost_type, id)); AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(GET_SHAPES); #undef GET_SHAPES AKANTU_DEBUG_OUT(); return *ret; } /* -------------------------------------------------------------------------- */ template <> inline const Array<Real> & FEEngineTemplate< IntegratorGauss, ShapeLinked, _ek_structural, DefaultIntegrationOrderFunctor>::getShapes(const ElementType & type, const GhostType & ghost_type, UInt id) const { AKANTU_DEBUG_IN(); const Array<Real> * ret = NULL; #define GET_SHAPES(type) \ ret = &(shape_functions.getShapes(type, ghost_type, id)); AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(GET_SHAPES); #undef GET_SHAPES AKANTU_DEBUG_OUT(); return *ret; } /* -------------------------------------------------------------------------- */ template <ElementKind kind, typename = void> struct AssembleFieldMatrixStructHelper {}; template <ElementKind kind> struct AssembleFieldMatrixStructHelper< kind, typename std::enable_if<kind == _ek_structural>::type> { template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind k, class IOF> static void call(const FEEngineTemplate<I, S, k, IOF> & fem, const Array<Real> & field_1, UInt nb_degree_of_freedom, SparseMatrix & M, Array<Real> * n, ElementTypeMapArray<Real> & rotation_mat, const ElementType & type, const GhostType & ghost_type) { #define ASSEMBLE_MATRIX(type) \ fem.template assembleFieldMatrix<type>(field_1, nb_degree_of_freedom, M, n, \ rotation_mat, ghost_type) AKANTU_BOOST_KIND_ELEMENT_SWITCH(ASSEMBLE_MATRIX, _ek_structural); #undef ASSEMBLE_MATRIX } }; template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::assembleFieldMatrix( const Array<Real> & field_1, UInt nb_degree_of_freedom, SparseMatrix & M, Array<Real> * n, ElementTypeMapArray<Real> & rotation_mat, const ElementType & type, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); AssembleFieldMatrixStructHelper<kind>::template call( *this, field_1, nb_degree_of_freedom, M, n, rotation_mat, type, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeShapesMatrix( const ElementType &, UInt, UInt, Array<Real> *, __attribute__((unused)) UInt, UInt, UInt, const bool, const GhostType &) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ template <> inline void FEEngineTemplate<IntegratorGauss, ShapeLinked, _ek_structural, DefaultIntegrationOrderFunctor>:: computeShapesMatrix(const ElementType & type, UInt nb_degree_of_freedom, UInt nb_nodes_per_element, Array<Real> * n, UInt id, UInt degree_to_interpolate, UInt degree_interpolated, const bool sign, // true +, false - const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt nb_element = mesh.getNbElement(type); UInt nb_quadrature_points = getNbIntegrationPoints(type); UInt nt_n_field_size = nb_degree_of_freedom * nb_nodes_per_element; UInt n_size = n->getNbComponent() / nt_n_field_size; Array<Real>::const_vector_iterator shape = getShapes(type, ghost_type, id).begin(nb_nodes_per_element); Array<Real>::matrix_iterator N_it = n->begin(n_size, nt_n_field_size); int c; if (sign == true) { c = 1; } else { c = -1; } UInt line = degree_interpolated; UInt coll = degree_to_interpolate; for (UInt e = 0; e < nb_element; ++e) { for (UInt q = 0; q < nb_quadrature_points; ++q, ++N_it, ++shape) { const Vector<Real> & shapes = *shape; Matrix<Real> & N = *N_it; N(line, coll) = shapes(0) * c; N(line, coll + nb_degree_of_freedom) = shapes(1) * c; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> template <ElementType type> inline void FEEngineTemplate<IntegratorGauss, ShapeLinked, _ek_structural, DefaultIntegrationOrderFunctor>:: assembleFieldMatrix(const Array<Real> & field_1, UInt nb_degree_of_freedom, SparseMatrix & M, Array<Real> * n, ElementTypeMapArray<Real> & rotation_mat, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); UInt nb_quadrature_points = getNbIntegrationPoints(type); UInt nt_n_field_size = nb_degree_of_freedom * nb_nodes_per_element; UInt n_size = n->getNbComponent() / nt_n_field_size; Array<Real> * nt_n_field = new Array<Real>( nb_element * nb_quadrature_points, // nt_n_size * nt_n_size, nb_elem * // nb_quad_points? nt_n_field_size * nt_n_field_size, "NT*N*field"); Array<Real> * nt = new Array<Real>(nb_element * nb_quadrature_points, n_size * nt_n_field_size, "N*T"); Array<Real> t = rotation_mat(type); nt_n_field->clear(); nt->clear(); Array<Real>::matrix_iterator N = n->begin(n_size, nt_n_field_size); Array<Real>::matrix_iterator Nt_N_field = nt_n_field->begin(nt_n_field_size, nt_n_field_size); Array<Real>::matrix_iterator T = rotation_mat(type).begin(nt_n_field_size, nt_n_field_size); Array<Real>::matrix_iterator NT = nt->begin(n_size, nt_n_field_size); Real * field_val = field_1.storage(); for (UInt e = 0; e < nb_element; ++e, ++T) { for (UInt q = 0; q < nb_quadrature_points; ++q, ++N, ++NT, ++Nt_N_field, /*++T,*/ ++field_val) { NT->mul<false, false>(*N, *T); Nt_N_field->mul<true, false>(*NT, *NT, *field_val); } } Array<Real> * int_nt_n_field = new Array<Real>( nb_element, nt_n_field_size * nt_n_field_size, "NT*N*field"); int_nt_n_field->clear(); integrate(*nt_n_field, *int_nt_n_field, nt_n_field_size * nt_n_field_size, type); // integrate(*nt_n_field, *int_nt_n_field, nb_degree_of_freedom, type); assembleMatrix(*int_nt_n_field, M, nb_degree_of_freedom, type); delete nt; delete nt_n_field; delete int_nt_n_field; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::assembleFieldMatrix( const Array<Real> & field_1, UInt nb_degree_of_freedom, SparseMatrix & M, Array<Real> * n, ElementTypeMapArray<Real> & rotation_mat, const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); } -__END_AKANTU__ +} // akantu diff --git a/src/fe_engine/gauss_integration.cc b/src/fe_engine/gauss_integration.cc index e9bc85558..d4f4d8caf 100644 --- a/src/fe_engine/gauss_integration.cc +++ b/src/fe_engine/gauss_integration.cc @@ -1,238 +1,238 @@ /** * @file integration_element.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Sébastien Hartmann <sebastien.hartmann@epfl.ch> * @author Thomas Menouillard <tmenouillard@stucky.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Thu Nov 05 2015 * * @brief Definition of the integration constants, some of the value are taken * from r3.01.01 doc from Code Aster * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "element_class.hh" using std::sqrt; -__BEGIN_AKANTU__ +namespace akantu { /* clang-format off */ /* -------------------------------------------------------------------------- */ /* Points */ /* -------------------------------------------------------------------------- */ template<> Real GaussIntegrationTypeData<_git_point, 1>::quad_positions[] = {0}; template<> Real GaussIntegrationTypeData<_git_point, 1>::quad_weights[] = {1.}; /* -------------------------------------------------------------------------- */ /* Segments */ /* -------------------------------------------------------------------------- */ template<> Real GaussIntegrationTypeData<_git_segment, 1>::quad_positions[] = {0.}; template<> Real GaussIntegrationTypeData<_git_segment, 1>::quad_weights[] = {2.}; /* -------------------------------------------------------------------------- */ template<> Real GaussIntegrationTypeData<_git_segment, 2>::quad_positions[] = {-1./sqrt(3.), 1./sqrt(3.)}; template<> Real GaussIntegrationTypeData<_git_segment, 2>::quad_weights[] = {1., 1.}; /* -------------------------------------------------------------------------- */ template<> Real GaussIntegrationTypeData<_git_segment, 3>::quad_positions[] = {-sqrt(3./5.), 0., sqrt(3./5.)}; template<> Real GaussIntegrationTypeData<_git_segment, 3>::quad_weights[] = {5./9., 8./9., 5./9.}; /* -------------------------------------------------------------------------- */ template<> Real GaussIntegrationTypeData<_git_segment, 4>::quad_positions[] = {-sqrt((3. + 2.*sqrt(6./5.))/7.), -sqrt((3. - 2.*sqrt(6./5.))/7.), sqrt((3. - 2.*sqrt(6./5.))/7.), sqrt((3. + 2.*sqrt(6./5.))/7.)}; template<> Real GaussIntegrationTypeData<_git_segment, 4>::quad_weights[] = {(18. - sqrt(30.))/36., (18. + sqrt(30.))/36., (18. + sqrt(30.))/36., (18. - sqrt(30.))/36.}; /* -------------------------------------------------------------------------- */ /* Triangles */ /* -------------------------------------------------------------------------- */ template<> Real GaussIntegrationTypeData<_git_triangle, 1>::quad_positions[] = {1./3., 1./3.}; template<> Real GaussIntegrationTypeData<_git_triangle, 1>::quad_weights[] = {1./2.}; /* -------------------------------------------------------------------------- */ template<> Real GaussIntegrationTypeData<_git_triangle, 3>::quad_positions[] = {1./6., 1./6., 2./3., 1./6., 1./6., 2./3.}; template<> Real GaussIntegrationTypeData<_git_triangle, 3>::quad_weights[] = {1./6., 1./6., 1./6.}; /* -------------------------------------------------------------------------- */ template<> Real GaussIntegrationTypeData<_git_triangle, 4>::quad_positions[] = {1./5., 1./5., 3./5., 1./5., 1./5., 3./5., 1./3., 1./3.}; template<> Real GaussIntegrationTypeData<_git_triangle, 4>::quad_weights[] = {25./(24.*4.), 25./(24.*4.), 25./(24.*4.), -27/(24.*4.)}; /* -------------------------------------------------------------------------- */ /// Found those one in the TrigGaussRuleInfo from mathematica and matched them to the code aster values /// http://www.colorado.edu/engineering/CAS/courses.d/AFEM.d/AFEM.AppI.d/AFEM.AppI.pdf static const Real tri_6_a = (8. - std::sqrt(10.) + std::sqrt(38.-44.*std::sqrt(2./5.)))/18.; static const Real tri_6_b = (8. - std::sqrt(10.) - std::sqrt(38.-44.*std::sqrt(2./5.)))/18.; static const Real tri_6_w1 = (620. - std::sqrt(213125. - 53320.*std::sqrt(10.)))/7440.; static const Real tri_6_w2 = (620. + std::sqrt(213125. - 53320.*std::sqrt(10.)))/7440.; template<> Real GaussIntegrationTypeData<_git_triangle, 6>::quad_positions[] = {tri_6_b, tri_6_b, 1. - 2. * tri_6_b, tri_6_b, tri_6_b, 1. - 2. * tri_6_b, tri_6_a, 1. - 2. * tri_6_a, tri_6_a, tri_6_a, 1. - 2. * tri_6_a, tri_6_a}; template<> Real GaussIntegrationTypeData<_git_triangle, 6>::quad_weights[] = {tri_6_w1, tri_6_w1, tri_6_w1, tri_6_w2, tri_6_w2, tri_6_w2}; /* -------------------------------------------------------------------------- */ static const Real tri_7_a = (6. + std::sqrt(15.)) / 21.; static const Real tri_7_b = (6. - std::sqrt(15.)) / 21.; static const Real tri_7_w1 = (155. + std::sqrt(15.))/2400.; static const Real tri_7_w2 = (155. - std::sqrt(15.))/2400.; template<> Real GaussIntegrationTypeData<_git_triangle, 7>::quad_positions[] = { 1./3., 1./3., tri_7_a, tri_7_a, 1. - 2.*tri_7_a, tri_7_a, tri_7_a, 1. - 2.*tri_7_a, tri_7_b, tri_7_b, 1. - 2.*tri_7_b, tri_7_b, tri_7_b, 1. - 2.*tri_7_b}; template<> Real GaussIntegrationTypeData<_git_triangle, 7>::quad_weights[] = {9./80., tri_7_w1, tri_7_w1, tri_7_w1, tri_7_w2, tri_7_w2, tri_7_w2}; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* Tetrahedrons */ /* -------------------------------------------------------------------------- */ template<> Real GaussIntegrationTypeData<_git_tetrahedron, 1>::quad_positions[] = {1./4., 1./4., 1./4.}; template<> Real GaussIntegrationTypeData<_git_tetrahedron, 1>::quad_weights[] = {1./6.}; /* -------------------------------------------------------------------------- */ static const Real tet_4_a = (5. - std::sqrt(5.))/20.; static const Real tet_4_b = (5. + 3.*std::sqrt(5.))/20.; template<> Real GaussIntegrationTypeData<_git_tetrahedron, 4>::quad_positions[] = {tet_4_a, tet_4_a, tet_4_a, tet_4_b, tet_4_a, tet_4_a, tet_4_a, tet_4_b, tet_4_a, tet_4_a, tet_4_a, tet_4_b}; template<> Real GaussIntegrationTypeData<_git_tetrahedron, 4>::quad_weights[] = {1./24., 1./24., 1./24., 1./24.}; /* -------------------------------------------------------------------------- */ template<> Real GaussIntegrationTypeData<_git_tetrahedron, 5>::quad_positions[] = {1./4., 1./4., 1./4., 1./6., 1./6., 1./6., 1./6., 1./6., 1./2., 1./6., 1./2., 1./6., 1./2., 1./6., 1./6.,}; template<> Real GaussIntegrationTypeData<_git_tetrahedron, 5>::quad_weights[] = {-2./15., 3./40., 3./40., 3./40., 3./40.}; /* -------------------------------------------------------------------------- */ static const Real tet_15_a = (7. + std::sqrt(15.))/34.; static const Real tet_15_b = (13. - 3. * std::sqrt(15.))/34.; static const Real tet_15_c = (7. - std::sqrt(15.))/34.; static const Real tet_15_d = (13. + 3. * std::sqrt(15.))/34.; static const Real tet_15_e = (5. - std::sqrt(15.))/20.; static const Real tet_15_f = (5. + std::sqrt(15.))/20.; static const Real tet_15_w1 = (2665. - 14. * std::sqrt(15.))/226800.; static const Real tet_15_w2 = (2665. + 14. * std::sqrt(15.))/226800.; static const Real tet_15_w3 = 5./567.; template<> Real GaussIntegrationTypeData<_git_tetrahedron, 15>::quad_positions[] = {1./4., 1./4., 1./4., tet_15_a, tet_15_a, tet_15_a, tet_15_a, tet_15_a, tet_15_b, tet_15_a, tet_15_b, tet_15_a, tet_15_b, tet_15_a, tet_15_a, tet_15_c, tet_15_c, tet_15_c, tet_15_c, tet_15_c, tet_15_d, tet_15_c, tet_15_d, tet_15_c, tet_15_d, tet_15_c, tet_15_c, tet_15_e, tet_15_e, tet_15_f, tet_15_e, tet_15_f, tet_15_e, tet_15_f, tet_15_e, tet_15_e, tet_15_e, tet_15_f, tet_15_f, tet_15_f, tet_15_e, tet_15_f, tet_15_f, tet_15_f, tet_15_e}; template<> Real GaussIntegrationTypeData<_git_tetrahedron, 15>::quad_weights[] = {8./405., tet_15_w1, tet_15_w1, tet_15_w1, tet_15_w1, tet_15_w2, tet_15_w2, tet_15_w2, tet_15_w2, tet_15_w3, tet_15_w3, tet_15_w3, tet_15_w3, tet_15_w3, tet_15_w3}; /* -------------------------------------------------------------------------- */ /* Pentahedrons */ /* -------------------------------------------------------------------------- */ template<> Real GaussIntegrationTypeData<_git_pentahedron, 6>::quad_positions[] = {-1./sqrt(3.), 0.5, 0.5, -1./sqrt(3.), 0. , 0.5, -1./sqrt(3.), 0.5, 0., 1./sqrt(3.), 0.5, 0.5, 1./sqrt(3.), 0. , 0.5, 1./sqrt(3.), 0.5 ,0.}; template<> Real GaussIntegrationTypeData<_git_pentahedron, 6>::quad_weights[] = {1./6., 1./6., 1./6., 1./6., 1./6., 1./6.}; /* -------------------------------------------------------------------------- */ template<> Real GaussIntegrationTypeData<_git_pentahedron, 8>::quad_positions[] = {-sqrt(3.)/3., 1./3., 1./3., -sqrt(3.)/3., 0.6, 0.2, -sqrt(3.)/3., 0.2, 0.6, -sqrt(3.)/3., 0.2, 0.2, sqrt(3.)/3., 1./3., 1./3., sqrt(3.)/3., 0.6, 0.2, sqrt(3.)/3., 0.2, 0.6, sqrt(3.)/3., 0.2, 0.2}; template<> Real GaussIntegrationTypeData<_git_pentahedron, 8>::quad_weights[] = {-27./96., 25./96., 25./96., 25./96., -27./96., 25./96., 25./96., 25./96.}; /* -------------------------------------------------------------------------- */ static const Real pent_21_x = std::sqrt(3./5.); static const Real pent_21_a = (6. + std::sqrt(15.)) / 21.; static const Real pent_21_b = (6. - std::sqrt(15.)) / 21.; static const Real pent_21_w1_1 = 5./9.; static const Real pent_21_w2_1 = 8./9.; static const Real pent_21_w1_2 = (155. + std::sqrt(15.))/2400.; static const Real pent_21_w2_2 = (155. - std::sqrt(15.))/2400.; template<> Real GaussIntegrationTypeData<_git_pentahedron, 21>::quad_positions[] = {- pent_21_x, 1./3., 1./3., - pent_21_x, pent_21_a, pent_21_a, - pent_21_x, 1. - 2.*pent_21_a, pent_21_a, - pent_21_x, pent_21_a, 1. - 2.*pent_21_a, - pent_21_x, pent_21_b, pent_21_b, - pent_21_x, 1. - 2.*pent_21_b, pent_21_b, - pent_21_x, pent_21_b, 1. - 2.*pent_21_b, 0., 1./3., 1./3., 0., pent_21_a, pent_21_a, 0., 1. - 2.*pent_21_a, pent_21_a, 0., pent_21_a, 1. - 2.*pent_21_a, 0., pent_21_b, pent_21_b, 0., 1. - 2.*pent_21_b, pent_21_b, 0., pent_21_b, 1. - 2.*pent_21_b, pent_21_x, 1./3., 1./3., pent_21_x, pent_21_a, pent_21_a, pent_21_x, 1. - 2.*pent_21_a, pent_21_a, pent_21_x, pent_21_a, 1. - 2.*pent_21_a, pent_21_x, pent_21_b, pent_21_b, pent_21_x, 1. - 2.*pent_21_b, pent_21_b, pent_21_x, pent_21_b, 1. - 2.*pent_21_b}; template<> Real GaussIntegrationTypeData<_git_pentahedron, 21>::quad_weights[] = {pent_21_w1_1 * 9. / 80., pent_21_w1_1*pent_21_w1_2, pent_21_w1_1*pent_21_w1_2, pent_21_w1_1*pent_21_w1_2, pent_21_w1_1*pent_21_w2_2, pent_21_w1_1*pent_21_w2_2, pent_21_w1_1*pent_21_w2_2, pent_21_w2_1 * 9. / 80., pent_21_w1_2*pent_21_w1_2, pent_21_w1_2*pent_21_w1_2, pent_21_w1_2*pent_21_w1_2, pent_21_w1_2*pent_21_w2_2, pent_21_w1_2*pent_21_w2_2, pent_21_w1_2*pent_21_w2_2, pent_21_w1_1 * 9. / 80., pent_21_w1_1*pent_21_w1_2, pent_21_w1_1*pent_21_w1_2, pent_21_w1_1*pent_21_w1_2, pent_21_w1_1*pent_21_w2_2, pent_21_w1_1*pent_21_w2_2, pent_21_w1_1*pent_21_w2_2}; -__END_AKANTU__ +} // akantu diff --git a/src/fe_engine/gauss_integration_tmpl.hh b/src/fe_engine/gauss_integration_tmpl.hh index 5498895f1..01b1aa7b3 100644 --- a/src/fe_engine/gauss_integration_tmpl.hh +++ b/src/fe_engine/gauss_integration_tmpl.hh @@ -1,271 +1,271 @@ /** * @file gauss_integration_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Tue May 10 10:48:21 2016 * * @brief implementation of the gauss integration helpers * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_GAUSS_INTEGRATION_TMPL_HH__ #define __AKANTU_GAUSS_INTEGRATION_TMPL_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* GaussIntegrationElement */ /* -------------------------------------------------------------------------- */ namespace _aka_gauss_helpers { template <GaussIntegrationType type, UInt n> struct GaussIntegrationNbPoints { }; template <UInt n> struct GaussIntegrationNbPoints<_git_not_defined, n> { static const UInt nb_points = 0; }; template <UInt n> struct GaussIntegrationNbPoints<_git_point, n> { static const UInt nb_points = 1; }; template <UInt n> struct GaussIntegrationNbPoints<_git_segment, n> { static const UInt nb_points = (n + 1) / 2 + ((n + 1) % 2 ? 1 : 0); }; #define DECLARE_GAUSS_NB_POINTS(type, order, points) \ template <> struct GaussIntegrationNbPoints<type, order> { \ static const UInt nb_points = points; \ } #define DECLARE_GAUSS_NB_POINTS_PENT(type, order, xo, yo) \ template <> struct GaussIntegrationNbPoints<type, order> { \ static const UInt x_order = xo; \ static const UInt yz_order = yo; \ static const UInt nb_points = 1; \ } DECLARE_GAUSS_NB_POINTS(_git_triangle, 1, 1); DECLARE_GAUSS_NB_POINTS(_git_triangle, 2, 3); DECLARE_GAUSS_NB_POINTS(_git_triangle, 3, 4); DECLARE_GAUSS_NB_POINTS(_git_triangle, 4, 6); DECLARE_GAUSS_NB_POINTS(_git_triangle, 5, 7); DECLARE_GAUSS_NB_POINTS(_git_tetrahedron, 1, 1); DECLARE_GAUSS_NB_POINTS(_git_tetrahedron, 2, 4); DECLARE_GAUSS_NB_POINTS(_git_tetrahedron, 3, 5); DECLARE_GAUSS_NB_POINTS(_git_tetrahedron, 4, 15); DECLARE_GAUSS_NB_POINTS(_git_tetrahedron, 5, 15); DECLARE_GAUSS_NB_POINTS_PENT(_git_pentahedron, 1, 3, 2); // order 3 in x, order 2 in y and z DECLARE_GAUSS_NB_POINTS_PENT(_git_pentahedron, 2, 3, 2); // order 3 in x, order 2 in y and z DECLARE_GAUSS_NB_POINTS_PENT(_git_pentahedron, 3, 3, 3); // order 3 in x, order 3 in y and z DECLARE_GAUSS_NB_POINTS_PENT(_git_pentahedron, 4, 5, 5); // order 5 in x, order 5 in y and z DECLARE_GAUSS_NB_POINTS_PENT(_git_pentahedron, 5, 5, 5); // order 5 in x, order 5 in y and z template <GaussIntegrationType type, UInt n, UInt on = n, bool end_recurse = false> struct GaussIntegrationNbPointsHelper { static const UInt pnp = GaussIntegrationNbPoints<type, n>::nb_points; static const UInt order = n; static const UInt nb_points = pnp; }; template <GaussIntegrationType type, UInt n, UInt on> struct GaussIntegrationNbPointsHelper<type, n, on, true> { static const UInt nb_points = 0; }; /* ------------------------------------------------------------------------ */ /* Generic helper */ /* ------------------------------------------------------------------------ */ template <GaussIntegrationType type, UInt dimension, UInt n> struct GaussIntegrationTypeDataHelper { typedef GaussIntegrationNbPoints<type, n> git_np; typedef GaussIntegrationTypeData<type, git_np::nb_points> git_data; static UInt getNbQuadraturePoints() { return git_np::nb_points; } static const Matrix<Real> getQuadraturePoints() { return Matrix<Real>(git_data::quad_positions, dimension, git_np::nb_points); } static const Vector<Real> getWeights() { return Vector<Real>(git_data::quad_weights, git_np::nb_points); } }; /* ------------------------------------------------------------------------ */ /* helper for _segment _quadrangle _hexahedron */ /* ------------------------------------------------------------------------ */ template <UInt dimension, UInt dp> struct GaussIntegrationTypeDataHelper<_git_segment, dimension, dp> { typedef GaussIntegrationNbPoints<_git_segment, dp> git_np; typedef GaussIntegrationTypeData<_git_segment, git_np::nb_points> git_data; static UInt getNbQuadraturePoints() { return Math::pow<dimension>(git_np::nb_points); } static const Matrix<Real> getQuadraturePoints() { UInt tot_nquad = getNbQuadraturePoints(); UInt nquad = git_np::nb_points; Matrix<Real> quads(dimension, tot_nquad); Vector<Real> pos(git_data::quad_positions, nquad); UInt offset = 1; for (UInt d = 0; d < dimension; ++d) { for (UInt n = 0, q = 0; n < tot_nquad; ++n, q += offset) { UInt rq = q % tot_nquad + q / tot_nquad; quads(d, rq) = pos(n % nquad); } offset *= nquad; } return quads; } static const Vector<Real> getWeights() { UInt tot_nquad = getNbQuadraturePoints(); UInt nquad = git_np::nb_points; Vector<Real> quads_weights(tot_nquad, 1.); Vector<Real> weights(git_data::quad_weights, nquad); UInt offset = 1; for (UInt d = 0; d < dimension; ++d) { for (UInt n = 0, q = 0; n < tot_nquad; ++n, q += offset) { UInt rq = q % tot_nquad + q / tot_nquad; quads_weights(rq) *= weights(n % nquad); } offset *= nquad; } return quads_weights; } }; /* ------------------------------------------------------------------------ */ /* helper for _pentahedron */ /* ------------------------------------------------------------------------ */ template <UInt dimension, UInt dp> struct GaussIntegrationTypeDataHelper<_git_pentahedron, dimension, dp> { typedef GaussIntegrationNbPoints<_git_pentahedron, dp> git_info; typedef GaussIntegrationNbPoints<_git_segment, git_info::x_order> git_np_seg; typedef GaussIntegrationNbPoints<_git_triangle, git_info::yz_order> git_np_tri; typedef GaussIntegrationTypeData<_git_segment, git_np_seg::nb_points> git_data_seg; typedef GaussIntegrationTypeData<_git_triangle, git_np_tri::nb_points> git_data_tri; static UInt getNbQuadraturePoints() { return git_np_seg::nb_points * git_np_tri::nb_points; } static const Matrix<Real> getQuadraturePoints() { UInt tot_nquad = getNbQuadraturePoints(); UInt nquad_seg = git_np_seg::nb_points; UInt nquad_tri = git_np_tri::nb_points; Matrix<Real> quads(dimension, tot_nquad); Matrix<Real> pos_seg_w(git_data_seg::quad_positions, 1, nquad_seg); Matrix<Real> pos_tri_w(git_data_tri::quad_positions, 2, nquad_tri); for (UInt ns = 0, q = 0; ns < nquad_seg; ++ns) { Vector<Real> pos_seg = pos_seg_w(ns); for (UInt nt = 0; nt < nquad_tri; ++nt, ++q) { Vector<Real> pos_tri = pos_tri_w(nt); Vector<Real> quad = quads(q); quad(_x) = pos_seg(_x); quad(_y) = pos_tri(_x); quad(_z) = pos_tri(_y); } } return quads; } static const Vector<Real> getWeights() { UInt tot_nquad = getNbQuadraturePoints(); UInt nquad_seg = git_np_seg::nb_points; UInt nquad_tri = git_np_tri::nb_points; Vector<Real> quads_weights(tot_nquad); Vector<Real> weight_seg(git_data_seg::quad_weights, nquad_seg); Vector<Real> weight_tri(git_data_tri::quad_weights, nquad_tri); for (UInt ns = 0, q = 0; ns < nquad_seg; ++ns) { for (UInt nt = 0; nt < nquad_tri; ++nt, ++q) { quads_weights(q) = weight_seg(ns) * weight_tri(nt); } } return quads_weights; } }; } template <ElementType element_type, UInt n> const Matrix<Real> GaussIntegrationElement<element_type, n>::getQuadraturePoints() { const InterpolationType itp_type = ElementClassProperty<element_type>::interpolation_type; typedef InterpolationPorperty<itp_type> interpolation_property; typedef _aka_gauss_helpers::GaussIntegrationTypeDataHelper< ElementClassProperty<element_type>::gauss_integration_type, interpolation_property::natural_space_dimension, n> data_helper; Matrix<Real> tmp(data_helper::getQuadraturePoints()); return tmp; } /* -------------------------------------------------------------------------- */ template <ElementType element_type, UInt n> const Vector<Real> GaussIntegrationElement<element_type, n>::getWeights() { const InterpolationType itp_type = ElementClassProperty<element_type>::interpolation_type; typedef InterpolationPorperty<itp_type> interpolation_property; typedef _aka_gauss_helpers::GaussIntegrationTypeDataHelper< ElementClassProperty<element_type>::gauss_integration_type, interpolation_property::natural_space_dimension, n> data_helper; Vector<Real> tmp(data_helper::getWeights()); return tmp; } /* -------------------------------------------------------------------------- */ template <ElementType element_type, UInt n> UInt GaussIntegrationElement<element_type, n>::getNbQuadraturePoints() { const InterpolationType itp_type = ElementClassProperty<element_type>::interpolation_type; typedef InterpolationPorperty<itp_type> interpolation_property; typedef _aka_gauss_helpers::GaussIntegrationTypeDataHelper< ElementClassProperty<element_type>::gauss_integration_type, interpolation_property::natural_space_dimension, n> data_helper; return data_helper::getNbQuadraturePoints(); } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_GAUSS_INTEGRATION_TMPL_HH__ */ diff --git a/src/fe_engine/geometrical_element.cc b/src/fe_engine/geometrical_element.cc index 35abaefc4..ce39baa40 100644 --- a/src/fe_engine/geometrical_element.cc +++ b/src/fe_engine/geometrical_element.cc @@ -1,209 +1,209 @@ /** * @file geometrical_element.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Thomas Menouillard <tmenouillard@stucky.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Thu Jan 21 2016 * * @brief Specialization of the geometrical types * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* clang-format off */ /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_not_defined>::spatial_dimension = 0; template<> UInt GeometricalElement<_gt_not_defined>::nb_nodes_per_element = 0; template<> UInt GeometricalElement<_gt_not_defined>::nb_facets[] = { 0 }; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_point>::spatial_dimension = 0; template<> UInt GeometricalElement<_gt_point>::nb_nodes_per_element = 1; template<> UInt GeometricalElement<_gt_point>::nb_facets[] = { 1 }; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_segment_2>::spatial_dimension = 1; template<> UInt GeometricalElement<_gt_segment_2>::nb_nodes_per_element = 2; template<> UInt GeometricalElement<_gt_segment_2>::nb_facets[] = { 2 }; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_segment_3>::spatial_dimension = 1; template<> UInt GeometricalElement<_gt_segment_3>::nb_nodes_per_element = 3; template<> UInt GeometricalElement<_gt_segment_3>::nb_facets[] = { 2 }; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_triangle_3>::spatial_dimension = 2; template<> UInt GeometricalElement<_gt_triangle_3>::nb_nodes_per_element = 3; template<> UInt GeometricalElement<_gt_triangle_3>::nb_facets[] = { 3 }; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_triangle_6>::spatial_dimension = 2; template<> UInt GeometricalElement<_gt_triangle_6>::nb_nodes_per_element = 6; template<> UInt GeometricalElement<_gt_triangle_6>::nb_facets[] = { 3 }; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_tetrahedron_4>::spatial_dimension = 3; template<> UInt GeometricalElement<_gt_tetrahedron_4>::nb_nodes_per_element = 4; template<> UInt GeometricalElement<_gt_tetrahedron_4>::nb_facets[] = { 4 }; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_tetrahedron_10>::spatial_dimension = 3; template<> UInt GeometricalElement<_gt_tetrahedron_10>::nb_nodes_per_element = 10; template<> UInt GeometricalElement<_gt_tetrahedron_10>::nb_facets[] = { 4 }; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_quadrangle_4>::spatial_dimension = 2; template<> UInt GeometricalElement<_gt_quadrangle_4>::nb_nodes_per_element = 4; template<> UInt GeometricalElement<_gt_quadrangle_4>::nb_facets[] = { 4 }; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_quadrangle_8>::spatial_dimension = 2; template<> UInt GeometricalElement<_gt_quadrangle_8>::nb_nodes_per_element = 8; template<> UInt GeometricalElement<_gt_quadrangle_8>::nb_facets[] = { 4 }; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_hexahedron_8>::spatial_dimension = 3; template<> UInt GeometricalElement<_gt_hexahedron_8>::nb_nodes_per_element = 8; template<> UInt GeometricalElement<_gt_hexahedron_8>::nb_facets[] = { 6 }; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_hexahedron_20>::spatial_dimension = 3; template<> UInt GeometricalElement<_gt_hexahedron_20>::nb_nodes_per_element = 20; template<> UInt GeometricalElement<_gt_hexahedron_20>::nb_facets[] = { 6 }; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_pentahedron_6>::spatial_dimension = 3; template<> UInt GeometricalElement<_gt_pentahedron_6>::nb_nodes_per_element = 6; template<> UInt GeometricalElement<_gt_pentahedron_6>::nb_facets[] = { 2, 3 }; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_pentahedron_15>::spatial_dimension = 3; template<> UInt GeometricalElement<_gt_pentahedron_15>::nb_nodes_per_element = 15; template<> UInt GeometricalElement<_gt_pentahedron_15>::nb_facets[] = { 2, 3 }; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_not_defined>::nb_nodes_per_facet[] = { 0 }; template<> UInt GeometricalElement<_gt_point>::nb_nodes_per_facet[] = { 1 }; template<> UInt GeometricalElement<_gt_segment_2>::nb_nodes_per_facet[] = { 1 }; template<> UInt GeometricalElement<_gt_segment_3>::nb_nodes_per_facet[] = { 1 }; template<> UInt GeometricalElement<_gt_triangle_3>::nb_nodes_per_facet[] = { 2 }; template<> UInt GeometricalElement<_gt_triangle_6>::nb_nodes_per_facet[] = { 3 }; template<> UInt GeometricalElement<_gt_tetrahedron_4>::nb_nodes_per_facet[] = { 3 }; template<> UInt GeometricalElement<_gt_tetrahedron_10>::nb_nodes_per_facet[] = { 6 }; template<> UInt GeometricalElement<_gt_quadrangle_4>::nb_nodes_per_facet[] = { 2 }; template<> UInt GeometricalElement<_gt_quadrangle_8>::nb_nodes_per_facet[] = { 3 }; template<> UInt GeometricalElement<_gt_hexahedron_8>::nb_nodes_per_facet[] = { 4 }; template<> UInt GeometricalElement<_gt_hexahedron_20>::nb_nodes_per_facet[] = { 8 }; template<> UInt GeometricalElement<_gt_pentahedron_6>::nb_nodes_per_facet[] = { 3, 4 }; template<> UInt GeometricalElement<_gt_pentahedron_15>::nb_nodes_per_facet[] = { 6, 8 }; /* -------------------------------------------------------------------------- */ template<> UInt GeometricalElement<_gt_not_defined>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_point>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_segment_2>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_segment_3>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_triangle_3>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_triangle_6>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_tetrahedron_4>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_tetrahedron_10>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_quadrangle_4>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_quadrangle_8>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_hexahedron_8>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_hexahedron_20>::nb_facet_types = 1; template<> UInt GeometricalElement<_gt_pentahedron_6>::nb_facet_types = 2; template<> UInt GeometricalElement<_gt_pentahedron_15>::nb_facet_types = 2; /* !!! stored as a matrix nb_facets X nb_nodes_per_facet in COL MAJOR */ /* -------------------------------------------------------------------------- */ /* f1|f2|f3|f4|f5|f6 */ template<> UInt GeometricalElement<_gt_not_defined>::facet_connectivity_vect[] = {0}; template<> UInt GeometricalElement<_gt_point>::facet_connectivity_vect[] = {0}; template<> UInt GeometricalElement<_gt_segment_2>::facet_connectivity_vect[] = {0, 1}; template<> UInt GeometricalElement<_gt_segment_3>::facet_connectivity_vect[] = {0, 1}; template<> UInt GeometricalElement<_gt_triangle_3>::facet_connectivity_vect[] = {0, 1, 2, 1, 2, 0}; template<> UInt GeometricalElement<_gt_triangle_6>::facet_connectivity_vect[] = {0, 1, 2, 1, 2, 0, 3, 4, 5}; template<> UInt GeometricalElement<_gt_tetrahedron_4>::facet_connectivity_vect[] = {0, 1, 2, 0, 2, 2, 0, 1, 1, 3, 3, 3}; template<> UInt GeometricalElement<_gt_tetrahedron_10>::facet_connectivity_vect[] = {0, 1, 2, 0, 2, 2, 0, 1, 1, 3, 3, 3, 6, 5, 6, 4, 5, 9, 7, 8, 4, 8, 9, 7}; template<> UInt GeometricalElement<_gt_quadrangle_4>::facet_connectivity_vect[] = {0, 1, 2, 3, 1, 2, 3, 0}; template<> UInt GeometricalElement<_gt_quadrangle_8>::facet_connectivity_vect[] = {0, 1, 2, 3, 1, 2, 3, 0, 4, 5, 6, 7}; template<> UInt GeometricalElement<_gt_hexahedron_8>::facet_connectivity_vect[] = {0, 0, 1, 2, 3, 4, 3, 1, 2, 3, 0, 5, 2, 5, 6, 7, 4, 6, 1, 4, 5, 6, 7, 7}; template<> UInt GeometricalElement<_gt_hexahedron_20>::facet_connectivity_vect[] = {0, 1, 2, 3, 0, 4, 1, 2, 3, 0, 3, 5, 5, 6, 7, 4, 2, 6, 4, 5, 6, 7, 1, 7, 8, 9, 10, 11, 11, 16, 13, 14, 15, 12, 10, 17, 16, 17, 18, 19, 9, 18, 12, 13, 14, 15, 8, 19}; template<> UInt GeometricalElement<_gt_pentahedron_6>::facet_connectivity_vect[] = {// first type 0, 3, 2, 4, 1, 5, // second type 0, 0, 1, 1, 3, 2, 4, 5, 5, 3, 2, 4}; template<> UInt GeometricalElement<_gt_pentahedron_15>::facet_connectivity_vect[] = {// first type 0, 3, 2, 4, 1, 5, 8, 12, 7, 13, 6, 14, // second type 0, 0, 1, 1, 3, 2, 4, 5, 5, 3, 2, 4, 6, 9, 7, 10, 14, 11, 12, 11, 13, 9, 8, 10}; template<> UInt * GeometricalElement<_gt_not_defined>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> UInt * GeometricalElement<_gt_point>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> UInt * GeometricalElement<_gt_segment_2>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> UInt * GeometricalElement<_gt_segment_3>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> UInt * GeometricalElement<_gt_triangle_3>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> UInt * GeometricalElement<_gt_triangle_6>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> UInt * GeometricalElement<_gt_tetrahedron_4>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> UInt * GeometricalElement<_gt_tetrahedron_10>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> UInt * GeometricalElement<_gt_quadrangle_4>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> UInt * GeometricalElement<_gt_quadrangle_8>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> UInt * GeometricalElement<_gt_hexahedron_8>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> UInt * GeometricalElement<_gt_hexahedron_20>::facet_connectivity[] = { &facet_connectivity_vect[0] }; template<> UInt * GeometricalElement<_gt_pentahedron_6>::facet_connectivity[] = { &facet_connectivity_vect[0], &facet_connectivity_vect[2*3] }; template<> UInt * GeometricalElement<_gt_pentahedron_15>::facet_connectivity[] = { &facet_connectivity_vect[0], &facet_connectivity_vect[2*6] }; /* clang-format on */ /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/fe_engine/integration_point.hh b/src/fe_engine/integration_point.hh index 58d3fbab9..fe0e493db 100644 --- a/src/fe_engine/integration_point.hh +++ b/src/fe_engine/integration_point.hh @@ -1,169 +1,169 @@ /** * @file integration_point.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Jun 17 2015 * @date last modification: Sun Nov 15 2015 * * @brief definition of the class IntegrationPoint * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_types.hh" #include "element.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_QUADRATURE_POINT_H #define AKANTU_QUADRATURE_POINT_H /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ class IntegrationPoint; extern const IntegrationPoint IntegrationPointNull; /* -------------------------------------------------------------------------- */ class IntegrationPoint : public Element { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: typedef Vector<Real> position_type; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: IntegrationPoint(const Element & element, UInt num_point = 0, UInt nb_quad_per_element = 0) : Element(element), num_point(num_point), global_num(element.element * nb_quad_per_element + num_point), position((Real *)NULL, 0){}; IntegrationPoint(ElementType type = _not_defined, UInt element = 0, UInt num_point = 0, GhostType ghost_type = _not_ghost) : Element(type, element, ghost_type), num_point(num_point), global_num(0), position((Real *)NULL, 0){}; IntegrationPoint(UInt element, UInt num_point, UInt global_num, const position_type & position, ElementType type, GhostType ghost_type = _not_ghost) : Element(type, element, ghost_type), num_point(num_point), global_num(global_num), position((Real *)NULL, 0) { this->position.shallowCopy(position); }; IntegrationPoint(const IntegrationPoint & quad) : Element(quad), num_point(quad.num_point), global_num(quad.global_num), position((Real *)NULL, 0) { position.shallowCopy(quad.position); }; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ inline bool operator==(const IntegrationPoint & quad) const { return Element::operator==(quad) && this->num_point == quad.num_point; } inline bool operator!=(const IntegrationPoint & quad) const { return ((element != quad.element) || (type != quad.type) || (ghost_type != quad.ghost_type) || (kind != quad.kind) || (num_point != quad.num_point) || (global_num != quad.global_num)); } bool operator<(const IntegrationPoint & rhs) const { bool res = Element::operator<(rhs) || (Element::operator==(rhs) && this->num_point < rhs.num_point); return res; } inline IntegrationPoint & operator=(const IntegrationPoint & q) { if (this != &q) { element = q.element; type = q.type; ghost_type = q.ghost_type; num_point = q.num_point; global_num = q.global_num; position.shallowCopy(q.position); } return *this; } /// get the position of the integration point AKANTU_GET_MACRO(Position, position, const position_type &); /// set the position of the integration point void setPosition(const position_type & position) { this->position.shallowCopy(position); } /// deep copy of the position of the integration point void copyPosition(const position_type & position) { this->position.deepCopy(position); } /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "IntegrationPoint ["; Element::printself(stream, 0); stream << ", " << num_point << "(" << global_num << ")" << "]"; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: /// number of quadrature point in the element UInt num_point; /// global number of the quadrature point UInt global_num; // TODO might be temporary: however this class should be tought maybe... std::string material_id; private: /// position of the quadrature point position_type position; }; /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const IntegrationPoint & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #endif /* AKANTU_QUADRATURE_POINT_H */ diff --git a/src/fe_engine/integrator.hh b/src/fe_engine/integrator.hh index 1f787abdf..7e22cfc4a 100644 --- a/src/fe_engine/integrator.hh +++ b/src/fe_engine/integrator.hh @@ -1,129 +1,129 @@ /** * @file integrator.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 22 2015 * * @brief interface for integrator classes * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_INTEGRATOR_HH__ #define __AKANTU_INTEGRATOR_HH__ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class Integrator : protected Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Integrator(const Mesh & mesh, const ID & id = "integrator", const MemoryID & memory_id = 0) : Memory(id, memory_id), mesh(mesh), jacobians("jacobians", id, memory_id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); }; virtual ~Integrator(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// empty method template <ElementType type> inline void precomputeJacobiansOnQuadraturePoints(__attribute__((unused)) GhostType ghost_type) {} /// empty method void integrateOnElement(__attribute__((unused)) const Array<Real> & f, __attribute__((unused)) Real * intf, __attribute__((unused)) UInt nb_degree_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 { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "Integrator [" << std::endl; jacobians.printself(stream, indent + 1); stream << space << "]" << std::endl; }; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// access to the jacobians Array<Real> & getJacobians(const ElementType & type, const GhostType & ghost_type = _not_ghost) { return jacobians(type, ghost_type); }; /// access to the jacobians const const Array<Real> & getJacobians(const ElementType & type, const GhostType & ghost_type = _not_ghost) const { return jacobians(type, ghost_type); }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// mesh associated to the integrator const Mesh & mesh; /// jacobians for all elements ElementTypeMapArray<Real> 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__ +} // akantu #endif /* __AKANTU_INTEGRATOR_HH__ */ diff --git a/src/fe_engine/integrator_gauss.hh b/src/fe_engine/integrator_gauss.hh index 0c810bb12..92e04f32a 100644 --- a/src/fe_engine/integrator_gauss.hh +++ b/src/fe_engine/integrator_gauss.hh @@ -1,182 +1,182 @@ /** * @file integrator_gauss.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 22 2015 * * @brief Gauss integration facilities * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_INTEGRATOR_GAUSS_HH__ #define __AKANTU_INTEGRATOR_GAUSS_HH__ /* -------------------------------------------------------------------------- */ #include "integrator.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { template <ElementKind kind, class IntegrationOrderFunctor> class IntegratorGauss : public Integrator { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: IntegratorGauss(const Mesh & mesh, const ID & id = "integrator_gauss", const MemoryID & memory_id = 0); virtual ~IntegratorGauss(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initIntegrator(const Array<Real> & nodes, const ElementType & type, const GhostType & ghost_type); template <ElementType type> inline void initIntegrator(const Array<Real> & nodes, const GhostType & ghost_type); /// integrate f on the element "elem" of type "type" template <ElementType type> inline void integrateOnElement(const Array<Real> & f, Real * intf, UInt nb_degree_of_freedom, const UInt elem, const GhostType & ghost_type) const; /// integrate f for all elements of type "type" template <ElementType type> void integrate(const Array<Real> & in_f, Array<Real> & intf, UInt nb_degree_of_freedom, const GhostType & ghost_type, const Array<UInt> & filter_elements) const; /// integrate scalar field in_f template <ElementType type, UInt polynomial_degree> Real integrate(const Array<Real> & in_f, const GhostType & ghost_type = _not_ghost) const; /// integrate partially around a quadrature point (@f$ intf_q = f_q * J_q * /// w_q @f$) template <ElementType type> Real integrate(const Vector<Real> & in_f, UInt index, const GhostType & ghost_type) const; /// integrate scalar field in_f template <ElementType type> Real integrate(const Array<Real> & in_f, const GhostType & ghost_type, const Array<UInt> & filter_elements) const; /// integrate a field without using the pre-computed values template <ElementType type, UInt polynomial_degree> void integrate(const Array<Real> & in_f, Array<Real> & intf, UInt nb_degree_of_freedom, const GhostType & ghost_type) const; /// integrate partially around a quadrature point (@f$ intf_q = f_q * J_q * /// w_q @f$) template <ElementType type> void integrateOnIntegrationPoints(const Array<Real> & in_f, Array<Real> & intf, UInt nb_degree_of_freedom, const GhostType & ghost_type, const Array<UInt> & filter_elements) const; /// return a matrix with quadrature points natural coordinates template <ElementType type> const Matrix<Real> & getIntegrationPoints(const GhostType & ghost_type) const; /// return number of quadrature points template <ElementType type> UInt getNbIntegrationPoints(const GhostType & ghost_type) const; template <ElementType type, UInt n> Matrix<Real> getIntegrationPoints() const; template <ElementType type, UInt n> Vector<Real> getIntegrationWeights() const; protected: template <ElementType type> void computeJacobiansOnIntegrationPoints(const Array<Real> & nodes, const Matrix<Real> & quad_points, Array<Real> & jacobians, const GhostType & ghost_type) const; /// precompute jacobians on elements of type "type" template <ElementType type> void precomputeJacobiansOnQuadraturePoints(const Array<Real> & nodes, const GhostType & ghost_type); // multiply the jacobians by the integration weights and stores the results in // jacobians template <ElementType type, UInt polynomial_degree> void multiplyJacobiansByWeights(Array<Real> & jacobians) const; /// compute the vector of quadrature points natural coordinates template <ElementType type> void computeQuadraturePoints(const GhostType & ghost_type); /// check that the jacobians are not negative template <ElementType type> void checkJacobians(const GhostType & ghost_type) const; /// internal integrate partially around a quadrature point (@f$ intf_q = f_q * /// J_q * /// w_q @f$) void integrateOnIntegrationPoints(const Array<Real> & in_f, Array<Real> & intf, UInt nb_degree_of_freedom, const Array<Real> & jacobians, UInt nb_element) const; void integrate(const Array<Real> & in_f, Array<Real> & intf, UInt nb_degree_of_freedom, const Array<Real> & jacobians, UInt nb_element) const; public: /// compute the jacobians on quad points for a given element template <ElementType type> void computeJacobianOnQuadPointsByElement(const Matrix<Real> & node_coords, const Matrix<Real> & integration_points, Vector<Real> & jacobians) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// integrate the field f with the jacobian jac -> inte inline void integrate(Real * f, Real * jac, Real * inte, UInt nb_degree_of_freedom, UInt nb_quadrature_points) const; private: /// ElementTypeMap of the quadrature points ElementTypeMap<Matrix<Real>> quadrature_points; }; -__END_AKANTU__ +} // akantu #include "integrator_gauss_inline_impl.cc" #endif /* __AKANTU_INTEGRATOR_GAUSS_HH__ */ diff --git a/src/fe_engine/integrator_gauss_inline_impl.cc b/src/fe_engine/integrator_gauss_inline_impl.cc index f2c578e29..387836053 100644 --- a/src/fe_engine/integrator_gauss_inline_impl.cc +++ b/src/fe_engine/integrator_gauss_inline_impl.cc @@ -1,561 +1,561 @@ /** * @file integrator_gauss_inline_impl.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Feb 15 2011 * @date last modification: Thu Nov 19 2015 * * @brief inline function of gauss integrator * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #include "fe_engine.hh" #if defined(AKANTU_DEBUG_TOOLS) #include "aka_debug_tools.hh" #endif -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> inline void IntegratorGauss<kind, IntegrationOrderFunctor>::integrateOnElement( const Array<Real> & f, Real * intf, UInt nb_degree_of_freedom, const UInt elem, const GhostType & ghost_type) const { Array<Real> & jac_loc = jacobians(type, ghost_type); UInt nb_quadrature_points = ElementClass<type>::getNbQuadraturePoints(); AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom, "The vector f do not have the good number of component."); Real * f_val = f.storage() + elem * f.getNbComponent(); Real * jac_val = jac_loc.storage() + elem * nb_quadrature_points; integrate(f_val, jac_val, intf, nb_degree_of_freedom, nb_quadrature_points); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> inline Real IntegratorGauss<kind, IntegrationOrderFunctor>::integrate( const Vector<Real> & in_f, UInt index, const GhostType & ghost_type) const { const Array<Real> & jac_loc = jacobians(type, ghost_type); UInt nb_quadrature_points = GaussIntegrationElement<type>::getNbQuadraturePoints(); AKANTU_DEBUG_ASSERT(in_f.size() == nb_quadrature_points, "The vector f do not have nb_quadrature_points entries."); Real * jac_val = jac_loc.storage() + index * nb_quadrature_points; Real intf; integrate(in_f.storage(), jac_val, &intf, 1, nb_quadrature_points); return intf; } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> inline void IntegratorGauss<kind, IntegrationOrderFunctor>::integrate( Real * f, Real * jac, Real * inte, UInt nb_degree_of_freedom, UInt nb_quadrature_points) const { memset(inte, 0, nb_degree_of_freedom * sizeof(Real)); Real * cjac = jac; for (UInt q = 0; q < nb_quadrature_points; ++q) { for (UInt dof = 0; dof < nb_degree_of_freedom; ++dof) { inte[dof] += *f * *cjac; ++f; } ++cjac; } } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> inline const Matrix<Real> & IntegratorGauss<kind, IntegrationOrderFunctor>::getIntegrationPoints( 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, ghost_type); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> inline UInt IntegratorGauss<kind, IntegrationOrderFunctor>::getNbIntegrationPoints( 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, ghost_type).cols(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type, UInt polynomial_degree> inline Matrix<Real> IntegratorGauss<kind, IntegrationOrderFunctor>::getIntegrationPoints() const { return GaussIntegrationElement<type, polynomial_degree>::getQuadraturePoints(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type, UInt polynomial_degree> inline Vector<Real> IntegratorGauss<kind, IntegrationOrderFunctor>::getIntegrationWeights() const { return GaussIntegrationElement<type, polynomial_degree>::getWeights(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> inline void IntegratorGauss<kind, IntegrationOrderFunctor>::computeQuadraturePoints( const GhostType & ghost_type) { Matrix<Real> & quads = quadrature_points(type, ghost_type); const UInt polynomial_degree = IntegrationOrderFunctor::template getOrder<type>(); quads = GaussIntegrationElement<type, polynomial_degree>::getQuadraturePoints(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> inline void IntegratorGauss<kind, IntegrationOrderFunctor>:: computeJacobianOnQuadPointsByElement(const Matrix<Real> & node_coords, const Matrix<Real> & quad, Vector<Real> & jacobians) const { // jacobian ElementClass<type>::computeJacobian(quad, node_coords, jacobians); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> IntegratorGauss<kind, IntegrationOrderFunctor>::IntegratorGauss( const Mesh & mesh, const ID & id, const MemoryID & memory_id) : Integrator(mesh, id, memory_id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> void IntegratorGauss<kind, IntegrationOrderFunctor>::checkJacobians( const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = this->quadrature_points(type, ghost_type).cols(); UInt nb_element = mesh.getConnectivity(type, ghost_type).getSize(); Real * jacobians_val = jacobians(type, ghost_type).storage(); for (UInt i = 0; i < nb_element * nb_quadrature_points; ++i, ++jacobians_val) { if (*jacobians_val < 0) AKANTU_DEBUG_ERROR( "Negative jacobian computed," << " possible problem in the element node ordering (Quadrature Point " << i % nb_quadrature_points << ":" << i / nb_quadrature_points << ":" << type << ":" << ghost_type << ")"); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> void IntegratorGauss<kind, IntegrationOrderFunctor>:: computeJacobiansOnIntegrationPoints(const Array<Real> & nodes, const Matrix<Real> & quad_points, Array<Real> & jacobians, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = quad_points.cols(); UInt nb_element = mesh.getNbElement(type, ghost_type); jacobians.resize(nb_element * nb_quadrature_points); Array<Real>::vector_iterator jacobians_it = jacobians.begin_reinterpret(nb_quadrature_points, nb_element); Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element); FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type); Array<Real>::const_matrix_iterator x_it = x_el.begin(spatial_dimension, nb_nodes_per_element); // Matrix<Real> local_coord(spatial_dimension, nb_nodes_per_element); for (UInt elem = 0; elem < nb_element; ++elem, ++jacobians_it, ++x_it) { const Matrix<Real> & x = *x_it; Vector<Real> & J = *jacobians_it; computeJacobianOnQuadPointsByElement<type>(x, quad_points, J); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ #if defined(AKANTU_COHESIVE_ELEMENT) template <> template <ElementType type> void IntegratorGauss<_ek_cohesive, DefaultIntegrationOrderFunctor>:: computeJacobiansOnIntegrationPoints(const Array<Real> & nodes, const Matrix<Real> & quad_points, Array<Real> & jacobians, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = quad_points.cols(); UInt nb_element = mesh.getNbElement(type, ghost_type); jacobians.resize(nb_element * nb_quadrature_points); Array<Real>::vector_iterator jacobians_it = jacobians.begin_reinterpret(nb_quadrature_points, nb_element); Vector<Real> weights = GaussIntegrationElement<type>::getWeights(); Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element); FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type); Array<Real>::const_matrix_iterator x_it = x_el.begin(spatial_dimension, nb_nodes_per_element); UInt nb_nodes_per_subelement = nb_nodes_per_element / 2; Matrix<Real> x(spatial_dimension, nb_nodes_per_subelement); for (UInt elem = 0; elem < nb_element; ++elem, ++jacobians_it, ++x_it) { for (UInt s = 0; s < spatial_dimension; ++s) for (UInt n = 0; n < nb_nodes_per_subelement; ++n) x(s, n) = ((*x_it)(s, n) + (*x_it)(s, n + nb_nodes_per_subelement)) * .5; Vector<Real> & J = *jacobians_it; if (type == _cohesive_1d_2) J(0) = 1; else computeJacobianOnQuadPointsByElement<type>(x, quad_points, J); } AKANTU_DEBUG_OUT(); } #endif /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> void IntegratorGauss<kind, IntegrationOrderFunctor>:: precomputeJacobiansOnQuadraturePoints(const Array<Real> & nodes, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); Array<Real> & jacobians_tmp = jacobians.alloc(0, 1, type, ghost_type); this->computeJacobiansOnIntegrationPoints<type>( nodes, quadrature_points(type, ghost_type), jacobians_tmp, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type, UInt polynomial_degree> void IntegratorGauss<kind, IntegrationOrderFunctor>::multiplyJacobiansByWeights( Array<Real> & jacobians) const { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = GaussIntegrationElement<type, polynomial_degree>::getNbQuadraturePoints(); UInt nb_element = jacobians.getSize() / nb_quadrature_points; Vector<Real> weights = GaussIntegrationElement<type, polynomial_degree>::getWeights(); Array<Real>::vector_iterator jacobians_it = jacobians.begin_reinterpret(nb_quadrature_points, nb_element); Array<Real>::vector_iterator jacobians_end = jacobians.end_reinterpret(nb_quadrature_points, nb_element); for (; jacobians_it != jacobians_end; ++jacobians_it) { Vector<Real> & J = *jacobians_it; J *= weights; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> void IntegratorGauss<kind, IntegrationOrderFunctor>::integrate( const Array<Real> & in_f, Array<Real> & intf, UInt nb_degree_of_freedom, const Array<Real> & jacobians, UInt nb_element) const { AKANTU_DEBUG_IN(); intf.resize(nb_element); if(nb_element == 0) return; UInt nb_points = jacobians.getSize() / nb_element; Array<Real>::const_matrix_iterator J_it; Array<Real>::matrix_iterator inte_it; Array<Real>::const_matrix_iterator f_it; f_it = in_f.begin_reinterpret(nb_degree_of_freedom, nb_points, nb_element); inte_it = intf.begin_reinterpret(nb_degree_of_freedom, 1, nb_element); J_it = jacobians.begin_reinterpret(nb_points, 1, nb_element); for (UInt el = 0; el < nb_element; ++el, ++J_it, ++f_it, ++inte_it) { const Matrix<Real> & f = *f_it; const Matrix<Real> & J = *J_it; Matrix<Real> & inte_f = *inte_it; inte_f.mul<false, false>(f, J); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> void IntegratorGauss<kind, IntegrationOrderFunctor>::integrate( const Array<Real> & in_f, Array<Real> & intf, UInt nb_degree_of_freedom, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type), "No jacobians for the type " << jacobians.printType(type, ghost_type)); const Array<Real> & jac_loc = jacobians(type, ghost_type); if (filter_elements != empty_filter) { UInt nb_element = filter_elements.getSize(); Array<Real> * filtered_J = new Array<Real>(0, jac_loc.getNbComponent()); FEEngine::filterElementalData(mesh, jac_loc, *filtered_J, type, ghost_type, filter_elements); this->integrate(in_f, intf, nb_degree_of_freedom, *filtered_J, nb_element); delete filtered_J; } else { UInt nb_element = mesh.getNbElement(type, ghost_type); this->integrate(in_f, intf, nb_degree_of_freedom, jac_loc, nb_element); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type, UInt polynomial_degree> void IntegratorGauss<kind, IntegrationOrderFunctor>::integrate( const Array<Real> & in_f, Array<Real> & intf, UInt nb_degree_of_freedom, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); Matrix<Real> quads = this->getIntegrationPoints<type, polynomial_degree>(); Array<Real> jacobians; this->computeJacobiansOnIntegrationPoints<type>(mesh.getNodes(), quads, jacobians, ghost_type); this->multiplyJacobiansByWeights<type, polynomial_degree>(jacobians); this->integrate(in_f, intf, nb_degree_of_freedom, jacobians, mesh.getNbElement(type, ghost_type)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type, UInt polynomial_degree> Real IntegratorGauss<kind, IntegrationOrderFunctor>::integrate( const Array<Real> & in_f, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); Array<Real> intfv(0, 1); integrate<type, polynomial_degree>(in_f, intfv, 1, ghost_type); Real res = Math::reduce(intfv); AKANTU_DEBUG_OUT(); return res; } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> Real IntegratorGauss<kind, IntegrationOrderFunctor>::integrate( const Array<Real> & in_f, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type), "No jacobians for the type " << jacobians.printType(type, ghost_type)); Array<Real> intfv(0, 1); integrate<type>(in_f, intfv, 1, ghost_type, filter_elements); Real res = Math::reduce(intfv); AKANTU_DEBUG_OUT(); return res; } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> void IntegratorGauss<kind, IntegrationOrderFunctor>:: integrateOnIntegrationPoints(const Array<Real> & in_f, Array<Real> & intf, UInt nb_degree_of_freedom, const Array<Real> & jacobians, UInt nb_element) const { AKANTU_DEBUG_IN(); UInt nb_points = jacobians.getSize() / nb_element; Array<Real>::const_scalar_iterator J_it; Array<Real>::vector_iterator inte_it; Array<Real>::const_vector_iterator f_it; intf.resize(nb_element * nb_points); J_it = jacobians.begin(); f_it = in_f.begin(nb_degree_of_freedom); inte_it = intf.begin(nb_degree_of_freedom); for (UInt el = 0; el < nb_element; ++el, ++J_it, ++f_it, ++inte_it) { const Real & J = *J_it; const Vector<Real> & f = *f_it; Vector<Real> & inte_f = *inte_it; inte_f = f; inte_f *= J; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> void IntegratorGauss<kind, IntegrationOrderFunctor>:: integrateOnIntegrationPoints(const Array<Real> & in_f, Array<Real> & intf, UInt nb_degree_of_freedom, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type), "No jacobians for the type " << jacobians.printType(type, ghost_type)); const Array<Real> & jac_loc = this->jacobians(type, ghost_type); if (filter_elements != empty_filter) { UInt nb_element = filter_elements.getSize(); Array<Real> * filtered_J = new Array<Real>(0, jac_loc.getNbComponent()); FEEngine::filterElementalData(mesh, jac_loc, *filtered_J, type, ghost_type, filter_elements); this->integrateOnIntegrationPoints(in_f, intf, nb_degree_of_freedom, *filtered_J, nb_element); } else { UInt nb_element = mesh.getNbElement(type, ghost_type); this->integrateOnIntegrationPoints(in_f, intf, nb_degree_of_freedom, jac_loc, nb_element); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> inline void IntegratorGauss<kind, IntegrationOrderFunctor>::initIntegrator( const Array<Real> & nodes, const GhostType & ghost_type) { computeQuadraturePoints<type>(ghost_type); precomputeJacobiansOnQuadraturePoints<type>(nodes, ghost_type); checkJacobians<type>(ghost_type); constexpr UInt polynomial_degree = IntegrationOrderFunctor::template getOrder<type>(); multiplyJacobiansByWeights<type, polynomial_degree>( this->jacobians(type, ghost_type)); } template <ElementKind kind> struct GaussIntegratorInitHelper {}; #define INIT_INTEGRATOR(type) \ _int.template initIntegrator<type>(nodes, ghost_type) #define AKANTU_GAUSS_INTERGRATOR_INIT_HELPER(kind) \ template <> struct GaussIntegratorInitHelper<kind> { \ template <ElementKind k, class IOF> \ static void call(IntegratorGauss<k, IOF> & _int, \ const Array<Real> & nodes, const ElementType & type, \ const GhostType & ghost_type) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(INIT_INTEGRATOR, kind); \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_GAUSS_INTERGRATOR_INIT_HELPER) #undef AKANTU_GAUSS_INTERGRATOR_INIT_HELPER #undef INIT_INTEGRATOR template <ElementKind kind, class IntegrationOrderFunctor> inline void IntegratorGauss<kind, IntegrationOrderFunctor>::initIntegrator( const Array<Real> & nodes, const ElementType & type, const GhostType & ghost_type) { GaussIntegratorInitHelper<kind>::call(*this, nodes, type, ghost_type); } -__END_AKANTU__ +} // akantu diff --git a/src/fe_engine/interpolation_element.cc b/src/fe_engine/interpolation_element.cc index b4291d578..cf5b90ed8 100644 --- a/src/fe_engine/interpolation_element.cc +++ b/src/fe_engine/interpolation_element.cc @@ -1,48 +1,48 @@ /** * @file interpolation_element.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Sun Oct 19 2014 * * @brief Common part of element_classes * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* Structural elements */ /* -------------------------------------------------------------------------- */ #if defined(AKANTU_STRUCTURAL_MECHANICS) template<> const UInt InterpolationElement<_itp_bernoulli_beam>::nb_shape_functions = 5; template<> const UInt InterpolationElement<_itp_kirchhoff_shell>::nb_shape_functions = 9; template<> const UInt InterpolationElement<_itp_bernoulli_beam>::nb_shape_derivatives = 3; template<> const UInt InterpolationElement<_itp_kirchhoff_shell>::nb_shape_derivatives = 7; #endif -__END_AKANTU__ +} // akantu diff --git a/src/fe_engine/shape_cohesive.hh b/src/fe_engine/shape_cohesive.hh index e6beca1bc..c2c5e4332 100644 --- a/src/fe_engine/shape_cohesive.hh +++ b/src/fe_engine/shape_cohesive.hh @@ -1,201 +1,201 @@ /** * @file shape_cohesive.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue Feb 15 2011 * @date last modification: Thu Oct 22 2015 * * @brief shape functions for cohesive elements description * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" #include "shape_functions.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SHAPE_COHESIVE_HH__ #define __AKANTU_SHAPE_COHESIVE_HH__ -__BEGIN_AKANTU__ +namespace akantu { struct CohesiveReduceFunctionMean { inline Real operator()(Real u_plus, Real u_minus) { return .5 * (u_plus + u_minus); } }; struct CohesiveReduceFunctionOpening { inline Real operator()(Real u_plus, Real u_minus) { return (u_plus - u_minus); } }; template <> class ShapeLagrange<_ek_cohesive> : public ShapeFunctions { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ShapeLagrange(const Mesh & mesh, const ID & id = "shape_cohesive", const MemoryID & memory_id = 0); virtual ~ShapeLagrange() {} /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: inline void initShapeFunctions(const Array<Real> & nodes, const Matrix<Real> & integration_points, const ElementType & type, const GhostType & ghost_type); /// extract the nodal values and store them per element template <ElementType type, class ReduceFunction> void extractNodalToElementField( const Array<Real> & nodal_f, Array<Real> & elemental_f, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const; /// pre compute all shapes on the element integration points from natural /// coordinates template <ElementType type> void precomputeShapesOnIntegrationPoints(const Array<Real> & nodes, GhostType ghost_type); /// pre compute all shape derivatives on the element integration points from /// natural coordinates template <ElementType type> void precomputeShapeDerivativesOnIntegrationPoints(const Array<Real> & nodes, GhostType ghost_type); /// interpolate nodal values on the integration points template <ElementType type, class ReduceFunction> void interpolateOnIntegrationPoints( const Array<Real> & u, Array<Real> & uq, UInt nb_degree_of_freedom, const GhostType ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const; template <ElementType type> void interpolateOnIntegrationPoints( const Array<Real> & u, Array<Real> & uq, UInt nb_degree_of_freedom, const GhostType ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const { interpolateOnIntegrationPoints<type, CohesiveReduceFunctionMean>( u, uq, nb_degree_of_freedom, ghost_type, filter_elements); } /// compute the gradient of u on the integration points in the natural /// coordinates template <ElementType type> void gradientOnIntegrationPoints( const Array<Real> & u, Array<Real> & nablauq, UInt nb_degree_of_freedom, GhostType ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const { variationOnIntegrationPoints<type, CohesiveReduceFunctionMean>( u, nablauq, nb_degree_of_freedom, ghost_type, filter_elements); } /// compute the gradient of u on the integration points template <ElementType type, class ReduceFunction> void variationOnIntegrationPoints( const Array<Real> & u, Array<Real> & nablauq, UInt nb_degree_of_freedom, GhostType ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const; /// compute the normals to the field u on integration points template <ElementType type, class ReduceFunction> void computeNormalsOnIntegrationPoints( const Array<Real> & u, Array<Real> & normals_u, GhostType ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const; /// multiply a field by shape functions template <ElementType type> void fieldTimesShapes(__attribute__((unused)) const Array<Real> & field, __attribute__((unused)) Array<Real> & fiedl_times_shapes, __attribute__((unused)) GhostType ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get a the shapes vector inline const Array<Real> & getShapes(const ElementType & el_type, const GhostType & ghost_type = _not_ghost) const; /// get a the shapes derivatives vector inline const Array<Real> & getShapesDerivatives(const ElementType & el_type, const GhostType & ghost_type = _not_ghost) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// shape functions for all elements ElementTypeMapArray<Real, InterpolationType> shapes; /// shape functions derivatives for all elements ElementTypeMapArray<Real, InterpolationType> shapes_derivatives; }; -// __END_AKANTU__ +// } // akantu // #include "shape_lagrange.hh" -// __BEGIN_AKANTU__ +// namespace akantu { // template<> // class ShapeLagrange<_ek_cohesive> : public ShapeCohesive< // ShapeLagrange<_ek_regular> > { // public: // ShapeLagrange(const Mesh & mesh, // const ID & id = "shape_cohesive", // const MemoryID & memory_id = 0) : // ShapeCohesive< ShapeLagrange<_ek_regular> >(mesh, id, memory_id) { } // virtual ~ShapeLagrange() { }; // }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "shape_cohesive_inline_impl.cc" /// standard output stream operator template <class ShapeFunction> inline std::ostream & operator<<(std::ostream & stream, const ShapeCohesive<ShapeFunction> & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_SHAPE_COHESIVE_HH__ */ diff --git a/src/fe_engine/shape_functions.hh b/src/fe_engine/shape_functions.hh index e4a1d1d3b..64a33e3d0 100644 --- a/src/fe_engine/shape_functions.hh +++ b/src/fe_engine/shape_functions.hh @@ -1,189 +1,189 @@ /** * @file shape_functions.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 22 2015 * * @brief shape function class * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SHAPE_FUNCTIONS_HH__ #define __AKANTU_SHAPE_FUNCTIONS_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ class ShapeFunctions : protected Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ShapeFunctions(const Mesh & mesh, const ID & id = "shape", const MemoryID & memory_id = 0) : Memory(id, memory_id), mesh(mesh){}; virtual ~ShapeFunctions(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "Shapes [" << std::endl; integration_points.printself(stream, indent + 1); stream << space << "]" << std::endl; }; /// set the integration points for a given element template <ElementType type> void setIntegrationPointsByType(const Matrix<Real> & integration_points, const GhostType & ghost_type); /// Build pre-computed matrices for interpolation of field form integration /// points at other given positions (interpolation_points) inline void initElementalFieldInterpolationFromIntegrationPoints( const ElementTypeMapArray<Real> & interpolation_points_coordinates, ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices, ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices, const ElementTypeMapArray<Real> & quadrature_points_coordinates, const ElementTypeMapArray<UInt> * element_filter) const; /// Interpolate field at given position from given values of this field at /// integration points (field) /// using matrices precomputed with /// initElementalFieldInterplationFromIntegrationPoints inline void interpolateElementalFieldFromIntegrationPoints( const ElementTypeMapArray<Real> & field, const ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices, const ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices, ElementTypeMapArray<Real> & result, const GhostType ghost_type, const ElementTypeMapArray<UInt> * element_filter) const; protected: /// interpolate nodal values stored by element on the integration points template <ElementType type> void interpolateElementalFieldOnIntegrationPoints( const Array<Real> & u_el, Array<Real> & uq, GhostType ghost_type, const Array<Real> & shapes, const Array<UInt> & filter_elements = empty_filter) const; /// gradient of nodal values stored by element on the control points template <ElementType type> void gradientElementalFieldOnIntegrationPoints( const Array<Real> & u_el, Array<Real> & out_nablauq, GhostType ghost_type, const Array<Real> & shapes_derivatives, const Array<UInt> & filter_elements) const; protected: /// By element versions of non-templated eponym methods template <ElementType type> inline void interpolateElementalFieldFromIntegrationPoints( const Array<Real> & field, const Array<Real> & interpolation_points_coordinates_matrices, const Array<Real> & quad_points_coordinates_inv_matrices, ElementTypeMapArray<Real> & result, const GhostType ghost_type, const Array<UInt> & element_filter) const; /// Interpolate field at given position from given values of this field at /// integration points (field) /// using matrices precomputed with /// initElementalFieldInterplationFromIntegrationPoints template <ElementType type> inline void initElementalFieldInterpolationFromIntegrationPoints( const Array<Real> & interpolation_points_coordinates, ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices, ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices, const Array<Real> & quadrature_points_coordinates, GhostType & ghost_type, const Array<UInt> & element_filter) const; /// build matrix for the interpolation of field form integration points template <ElementType type> inline void buildElementalFieldInterpolationMatrix( const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix, UInt integration_order = ElementClassProperty<type>::polynomial_degree) const; /// build the so called interpolation matrix (first collumn is 1, then the /// other collumns are the traansposed coordinates) inline void buildInterpolationMatrix(const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix, UInt integration_order) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// 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); inline const Matrix<Real> & getIntegrationPoints(const ElementType & type, const GhostType & ghost_type) const { return integration_points(type, ghost_type); } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// associated mesh const Mesh & mesh; /// shape functions for all elements ElementTypeMap<Matrix<Real> > integration_points; }; #if defined(AKANTU_INCLUDE_INLINE_IMPL) #include "shape_functions_inline_impl.cc" #endif /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const ShapeFunctions & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_SHAPE_FUNCTIONS_HH__ */ diff --git a/src/fe_engine/shape_functions_inline_impl.cc b/src/fe_engine/shape_functions_inline_impl.cc index 51bae3df1..c09c2d643 100644 --- a/src/fe_engine/shape_functions_inline_impl.cc +++ b/src/fe_engine/shape_functions_inline_impl.cc @@ -1,609 +1,609 @@ /** * @file shape_functions_inline_impl.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Fabian Barras <fabian.barras@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Oct 27 2010 * @date last modification: Thu Oct 15 2015 * * @brief ShapeFunctions inline implementation * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #include "fe_engine.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ inline UInt ShapeFunctions::getShapeSize(const ElementType & type) { AKANTU_DEBUG_IN(); UInt shape_size = 0; #define GET_SHAPE_SIZE(type) shape_size = ElementClass<type>::getShapeSize() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_SHAPE_SIZE); // , #undef GET_SHAPE_SIZE AKANTU_DEBUG_OUT(); return shape_size; } /* -------------------------------------------------------------------------- */ inline UInt ShapeFunctions::getShapeDerivativesSize(const ElementType & type) { AKANTU_DEBUG_IN(); UInt shape_derivatives_size = 0; #define GET_SHAPE_DERIVATIVES_SIZE(type) \ shape_derivatives_size = ElementClass<type>::getShapeDerivativesSize() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_SHAPE_DERIVATIVES_SIZE); // , #undef GET_SHAPE_DERIVATIVES_SIZE AKANTU_DEBUG_OUT(); return shape_derivatives_size; } /* -------------------------------------------------------------------------- */ template <ElementType type> void ShapeFunctions::setIntegrationPointsByType(const Matrix<Real> & points, const GhostType & ghost_type) { integration_points(type, ghost_type).shallowCopy(points); } /* -------------------------------------------------------------------------- */ inline void ShapeFunctions::initElementalFieldInterpolationFromIntegrationPoints( const ElementTypeMapArray<Real> & interpolation_points_coordinates, ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices, ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices, const ElementTypeMapArray<Real> & quadrature_points_coordinates, const ElementTypeMapArray<UInt> * element_filter) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = this->mesh.getSpatialDimension(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Mesh::type_iterator it, last; if (element_filter) { it = element_filter->firstType(spatial_dimension, ghost_type); last = element_filter->lastType(spatial_dimension, ghost_type); } else { it = mesh.firstType(spatial_dimension, ghost_type); last = mesh.lastType(spatial_dimension, ghost_type); } for (; it != last; ++it) { ElementType type = *it; UInt nb_element = mesh.getNbElement(type, ghost_type); if (nb_element == 0) continue; const Array<UInt> * elem_filter; if (element_filter) elem_filter = &((*element_filter)(type, ghost_type)); else elem_filter = &(empty_filter); #define AKANTU_INIT_ELEMENTAL_FIELD_INTERPOLATION_FROM_C_POINTS(type) \ initElementalFieldInterpolationFromIntegrationPoints<type>( \ interpolation_points_coordinates(type, ghost_type), \ interpolation_points_coordinates_matrices, \ quad_points_coordinates_inv_matrices, \ quadrature_points_coordinates(type, ghost_type), ghost_type, \ *elem_filter) AKANTU_BOOST_REGULAR_ELEMENT_SWITCH( AKANTU_INIT_ELEMENTAL_FIELD_INTERPOLATION_FROM_C_POINTS); #undef AKANTU_INIT_ELEMENTAL_FIELD_INTERPOLATION_FROM_C_POINTS } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementType type> inline void ShapeFunctions::initElementalFieldInterpolationFromIntegrationPoints( const Array<Real> & interpolation_points_coordinates, ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices, ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices, const Array<Real> & quadrature_points_coordinates, GhostType & ghost_type, const Array<UInt> & element_filter) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = this->mesh.getSpatialDimension(); UInt nb_element = this->mesh.getNbElement(type, ghost_type); UInt nb_element_filter; if (element_filter == empty_filter) nb_element_filter = nb_element; else nb_element_filter = element_filter.getSize(); UInt nb_quad_per_element = GaussIntegrationElement<type>::getNbQuadraturePoints(); UInt nb_interpolation_points_per_elem = interpolation_points_coordinates.getSize() / nb_element; AKANTU_DEBUG_ASSERT(interpolation_points_coordinates.getSize() % nb_element == 0, "Number of interpolation points should be a multiple of " "total number of elements"); if (!quad_points_coordinates_inv_matrices.exists(type, ghost_type)) quad_points_coordinates_inv_matrices.alloc( nb_element_filter, nb_quad_per_element * nb_quad_per_element, type, ghost_type); else quad_points_coordinates_inv_matrices(type, ghost_type) .resize(nb_element_filter); if (!interpolation_points_coordinates_matrices.exists(type, ghost_type)) interpolation_points_coordinates_matrices.alloc( nb_element_filter, nb_interpolation_points_per_elem * nb_quad_per_element, type, ghost_type); else interpolation_points_coordinates_matrices(type, ghost_type) .resize(nb_element_filter); Array<Real> & quad_inv_mat = quad_points_coordinates_inv_matrices(type, ghost_type); Array<Real> & interp_points_mat = interpolation_points_coordinates_matrices(type, ghost_type); Matrix<Real> quad_coord_matrix(nb_quad_per_element, nb_quad_per_element); Array<Real>::const_matrix_iterator quad_coords_it = quadrature_points_coordinates.begin_reinterpret( spatial_dimension, nb_quad_per_element, nb_element_filter); Array<Real>::const_matrix_iterator points_coords_begin = interpolation_points_coordinates.begin_reinterpret( spatial_dimension, nb_interpolation_points_per_elem, nb_element); Array<Real>::matrix_iterator inv_quad_coord_it = quad_inv_mat.begin(nb_quad_per_element, nb_quad_per_element); Array<Real>::matrix_iterator int_points_mat_it = interp_points_mat.begin( nb_interpolation_points_per_elem, nb_quad_per_element); /// loop over the elements of the current material and element type for (UInt el = 0; el < nb_element_filter; ++el, ++inv_quad_coord_it, ++int_points_mat_it, ++quad_coords_it) { /// matrix containing the quadrature points coordinates const Matrix<Real> & quad_coords = *quad_coords_it; /// matrix to store the matrix inversion result Matrix<Real> & inv_quad_coord_matrix = *inv_quad_coord_it; /// insert the quad coordinates in a matrix compatible with the /// interpolation buildElementalFieldInterpolationMatrix<type>(quad_coords, quad_coord_matrix); /// invert the interpolation matrix inv_quad_coord_matrix.inverse(quad_coord_matrix); /// matrix containing the interpolation points coordinates const Matrix<Real> & points_coords = points_coords_begin[element_filter(el)]; /// matrix to store the interpolation points coordinates /// compatible with these functions Matrix<Real> & inv_points_coord_matrix = *int_points_mat_it; /// insert the quad coordinates in a matrix compatible with the /// interpolation buildElementalFieldInterpolationMatrix<type>(points_coords, inv_points_coord_matrix); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void ShapeFunctions::buildInterpolationMatrix(const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix, UInt integration_order) const { switch (integration_order) { case 1: { for (UInt i = 0; i < coordinates.cols(); ++i) coordMatrix(i, 0) = 1; break; } case 2: { UInt nb_quadrature_points = coordMatrix.cols(); for (UInt i = 0; i < coordinates.cols(); ++i) { coordMatrix(i, 0) = 1; for (UInt j = 1; j < nb_quadrature_points; ++j) coordMatrix(i, j) = coordinates(j - 1, i); } break; } default: { AKANTU_DEBUG_TO_IMPLEMENT(); break; } } } /* -------------------------------------------------------------------------- */ template <ElementType type> inline void ShapeFunctions::buildElementalFieldInterpolationMatrix( __attribute__((unused)) const Matrix<Real> & coordinates, __attribute__((unused)) Matrix<Real> & coordMatrix, __attribute__((unused)) UInt integration_order) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ template <> inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_segment_2>( const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix, UInt integration_order) const { buildInterpolationMatrix(coordinates, coordMatrix, integration_order); } /* -------------------------------------------------------------------------- */ template <> inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_segment_3>( const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix, UInt integration_order) const { buildInterpolationMatrix(coordinates, coordMatrix, integration_order); } /* -------------------------------------------------------------------------- */ template <> inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_triangle_3>( const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix, UInt integration_order) const { buildInterpolationMatrix(coordinates, coordMatrix, integration_order); } /* -------------------------------------------------------------------------- */ template <> inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_triangle_6>( const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix, UInt integration_order) const { buildInterpolationMatrix(coordinates, coordMatrix, integration_order); } /* -------------------------------------------------------------------------- */ template <> inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_tetrahedron_4>( const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix, UInt integration_order) const { buildInterpolationMatrix(coordinates, coordMatrix, integration_order); } /* -------------------------------------------------------------------------- */ template <> inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_tetrahedron_10>( const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix, UInt integration_order) const { buildInterpolationMatrix(coordinates, coordMatrix, integration_order); } /** * @todo Write a more efficient interpolation for quadrangles by * dropping unnecessary quadrature points * */ /* -------------------------------------------------------------------------- */ template <> inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_quadrangle_4>( const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix, UInt integration_order) const { if (integration_order != ElementClassProperty<_quadrangle_4>::polynomial_degree) { AKANTU_DEBUG_TO_IMPLEMENT(); } else { for (UInt i = 0; i < coordinates.cols(); ++i) { Real x = coordinates(0, i); Real y = coordinates(1, i); coordMatrix(i, 0) = 1; coordMatrix(i, 1) = x; coordMatrix(i, 2) = y; coordMatrix(i, 3) = x * y; } } } /* -------------------------------------------------------------------------- */ template <> inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_quadrangle_8>( const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix, UInt integration_order) const { if (integration_order != ElementClassProperty<_quadrangle_8>::polynomial_degree) { AKANTU_DEBUG_TO_IMPLEMENT(); } else { for (UInt i = 0; i < coordinates.cols(); ++i) { UInt j = 0; Real x = coordinates(0, i); Real y = coordinates(1, i); for (UInt e = 0; e <= 2; ++e) { for (UInt n = 0; n <= 2; ++n) { coordMatrix(i, j) = std::pow(x, e) * std::pow(y, n); ++j; } } } } } /* -------------------------------------------------------------------------- */ void ShapeFunctions::interpolateElementalFieldFromIntegrationPoints( const ElementTypeMapArray<Real> & field, const ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices, const ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices, ElementTypeMapArray<Real> & result, const GhostType ghost_type, const ElementTypeMapArray<UInt> * element_filter) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = this->mesh.getSpatialDimension(); Mesh::type_iterator it, last; if (element_filter) { it = element_filter->firstType(spatial_dimension, ghost_type); last = element_filter->lastType(spatial_dimension, ghost_type); } else { it = mesh.firstType(spatial_dimension, ghost_type); last = mesh.lastType(spatial_dimension, ghost_type); } for (; it != last; ++it) { ElementType type = *it; UInt nb_element = mesh.getNbElement(type, ghost_type); if (nb_element == 0) continue; const Array<UInt> * elem_filter; if (element_filter) elem_filter = &((*element_filter)(type, ghost_type)); else elem_filter = &(empty_filter); #define AKANTU_INTERPOLATE_ELEMENTAL_FIELD_FROM_C_POINTS(type) \ interpolateElementalFieldFromIntegrationPoints<type>( \ field(type, ghost_type), \ interpolation_points_coordinates_matrices(type, ghost_type), \ quad_points_coordinates_inv_matrices(type, ghost_type), result, \ ghost_type, *elem_filter) AKANTU_BOOST_REGULAR_ELEMENT_SWITCH( AKANTU_INTERPOLATE_ELEMENTAL_FIELD_FROM_C_POINTS); #undef AKANTU_INTERPOLATE_ELEMENTAL_FIELD_FROM_C_POINTS } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementType type> inline void ShapeFunctions::interpolateElementalFieldFromIntegrationPoints( const Array<Real> & field, const Array<Real> & interpolation_points_coordinates_matrices, const Array<Real> & quad_points_coordinates_inv_matrices, ElementTypeMapArray<Real> & result, const GhostType ghost_type, const Array<UInt> & element_filter) const { AKANTU_DEBUG_IN(); UInt nb_element = this->mesh.getNbElement(type, ghost_type); UInt nb_quad_per_element = GaussIntegrationElement<type>::getNbQuadraturePoints(); UInt nb_interpolation_points_per_elem = interpolation_points_coordinates_matrices.getNbComponent() / nb_quad_per_element; if (!result.exists(type, ghost_type)) result.alloc(nb_element * nb_interpolation_points_per_elem, field.getNbComponent(), type, ghost_type); if (element_filter != empty_filter) nb_element = element_filter.getSize(); Matrix<Real> coefficients(nb_quad_per_element, field.getNbComponent()); Array<Real> & result_vec = result(type, ghost_type); Array<Real>::const_matrix_iterator field_it = field.begin_reinterpret( field.getNbComponent(), nb_quad_per_element, nb_element); Array<Real>::const_matrix_iterator interpolation_points_coordinates_it = interpolation_points_coordinates_matrices.begin( nb_interpolation_points_per_elem, nb_quad_per_element); Array<Real>::matrix_iterator result_begin = result_vec.begin_reinterpret( field.getNbComponent(), nb_interpolation_points_per_elem, result_vec.getSize() / nb_interpolation_points_per_elem); Array<Real>::const_matrix_iterator inv_quad_coord_it = quad_points_coordinates_inv_matrices.begin(nb_quad_per_element, nb_quad_per_element); /// loop over the elements of the current filter and element type for (UInt el = 0; el < nb_element; ++el, ++field_it, ++inv_quad_coord_it, ++interpolation_points_coordinates_it) { /** * matrix containing the inversion of the quadrature points' * coordinates */ const Matrix<Real> & inv_quad_coord_matrix = *inv_quad_coord_it; /** * multiply it by the field values over quadrature points to get * the interpolation coefficients */ coefficients.mul<false, true>(inv_quad_coord_matrix, *field_it); /// matrix containing the points' coordinates const Matrix<Real> & coord = *interpolation_points_coordinates_it; /// multiply the coordinates matrix by the coefficients matrix and store the /// result Matrix<Real> res(result_begin[element_filter(el)]); res.mul<true, true>(coefficients, coord); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementType type> inline void ShapeFunctions::interpolateElementalFieldOnIntegrationPoints( const Array<Real> & u_el, Array<Real> & uq, GhostType ghost_type, const Array<Real> & shapes, const Array<UInt> & filter_elements) const { UInt nb_element; UInt nb_nodes_per_element = ElementClass<type>::getShapeSize(); UInt nb_points = shapes.getSize() / mesh.getNbElement(type, ghost_type); UInt nb_degree_of_freedom = u_el.getNbComponent() / nb_nodes_per_element; Array<Real>::const_matrix_iterator N_it; Array<Real>::const_matrix_iterator u_it; Array<Real>::matrix_iterator inter_u_it; Array<Real> * filtered_N = NULL; if (filter_elements != empty_filter) { nb_element = filter_elements.getSize(); filtered_N = new Array<Real>(0, shapes.getNbComponent()); FEEngine::filterElementalData(mesh, shapes, *filtered_N, type, ghost_type, filter_elements); N_it = filtered_N->begin_reinterpret(nb_nodes_per_element, nb_points, nb_element); } else { nb_element = mesh.getNbElement(type, ghost_type); N_it = shapes.begin_reinterpret(nb_nodes_per_element, nb_points, nb_element); } uq.resize(nb_element * nb_points); u_it = u_el.begin(nb_degree_of_freedom, nb_nodes_per_element); inter_u_it = uq.begin_reinterpret(nb_degree_of_freedom, nb_points, nb_element); for (UInt el = 0; el < nb_element; ++el, ++N_it, ++u_it, ++inter_u_it) { const Matrix<Real> & u = *u_it; const Matrix<Real> & N = *N_it; Matrix<Real> & inter_u = *inter_u_it; inter_u.mul<false, false>(u, N); } delete filtered_N; } /* -------------------------------------------------------------------------- */ template <ElementType type> void ShapeFunctions::gradientElementalFieldOnIntegrationPoints( const Array<Real> & u_el, Array<Real> & out_nablauq, GhostType ghost_type, const Array<Real> & shapes_derivatives, const Array<UInt> & filter_elements) const { AKANTU_DEBUG_IN(); UInt nb_nodes_per_element = ElementClass<type>::getNbNodesPerInterpolationElement(); UInt nb_points = integration_points(type, ghost_type).cols(); UInt element_dimension = ElementClass<type>::getNaturalSpaceDimension(); UInt nb_degree_of_freedom = u_el.getNbComponent() / nb_nodes_per_element; Array<Real>::const_matrix_iterator B_it; Array<Real>::const_matrix_iterator u_it; Array<Real>::matrix_iterator nabla_u_it; UInt nb_element; Array<Real> * filtered_B = NULL; if (filter_elements != empty_filter) { nb_element = filter_elements.getSize(); filtered_B = new Array<Real>(0, shapes_derivatives.getNbComponent()); FEEngine::filterElementalData(mesh, shapes_derivatives, *filtered_B, type, ghost_type, filter_elements); B_it = filtered_B->begin(element_dimension, nb_nodes_per_element); } else { B_it = shapes_derivatives.begin(element_dimension, nb_nodes_per_element); nb_element = mesh.getNbElement(type, ghost_type); } out_nablauq.resize(nb_element * nb_points); u_it = u_el.begin(nb_degree_of_freedom, nb_nodes_per_element); nabla_u_it = out_nablauq.begin(nb_degree_of_freedom, element_dimension); for (UInt el = 0; el < nb_element; ++el, ++u_it) { const Matrix<Real> & u = *u_it; for (UInt q = 0; q < nb_points; ++q, ++B_it, ++nabla_u_it) { const Matrix<Real> & B = *B_it; Matrix<Real> & nabla_u = *nabla_u_it; nabla_u.mul<false, true>(u, B); } } delete filtered_B; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ diff --git a/src/fe_engine/shape_lagrange.hh b/src/fe_engine/shape_lagrange.hh index 2a75648fd..c8a074bd3 100644 --- a/src/fe_engine/shape_lagrange.hh +++ b/src/fe_engine/shape_lagrange.hh @@ -1,185 +1,185 @@ /** * @file shape_lagrange.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Feb 15 2011 * @date last modification: Thu Nov 05 2015 * * @brief lagrangian shape functions class * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_SHAPE_LAGRANGE_HH__ #define __AKANTU_SHAPE_LAGRANGE_HH__ #include "shape_functions.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <class Shape> class ShapeCohesive; class ShapeIGFEM; template <ElementKind kind> class ShapeLagrange : public ShapeFunctions { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ShapeLagrange(const Mesh & mesh, const ID & id = "shape_lagrange", const MemoryID & memory_id = 0); virtual ~ShapeLagrange(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialization function for structural elements not yet implemented inline void initShapeFunctions(const Array<Real> & nodes, const Matrix<Real> & integration_points, const ElementType & type, const GhostType & ghost_type); /// computes the shape functions for given interpolation points template <ElementType type> void computeShapesOnIntegrationPoints(const Array<Real> & nodes, const Matrix<Real> & integration_points, Array<Real> & shapes, const GhostType & ghost_type) const; /// computes the shape functions derivatives for given interpolation points template <ElementType type> void computeShapeDerivativesOnIntegrationPoints( const Array<Real> & nodes, const Matrix<Real> & integration_points, Array<Real> & shape_derivatives, const GhostType & ghost_type) const; /// pre compute all shapes on the element integration points from natural /// coordinates template <ElementType type> void precomputeShapesOnIntegrationPoints(const Array<Real> & nodes, const GhostType & ghost_type); /// pre compute all shape derivatives on the element integration points from /// natural coordinates template <ElementType type> void precomputeShapeDerivativesOnIntegrationPoints(const Array<Real> & nodes, const GhostType & ghost_type); /// interpolate nodal values on the integration points template <ElementType type> void interpolateOnIntegrationPoints( const Array<Real> & u, Array<Real> & uq, UInt nb_degree_of_freedom, GhostType ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const; template <ElementType type> void interpolateOnIntegrationPoints( const Array<Real> & in_u, Array<Real> & out_uq, UInt nb_degree_of_freedom, const Array<Real> & shapes, GhostType ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const; /// interpolate on physical point template <ElementType type> void interpolate(const Vector<Real> & real_coords, UInt elem, const Matrix<Real> & nodal_values, Vector<Real> & interpolated, const GhostType & ghost_type) const; /// compute the gradient of u on the integration points template <ElementType type> void gradientOnIntegrationPoints( const Array<Real> & u, Array<Real> & nablauq, UInt nb_degree_of_freedom, GhostType ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter) const; /// multiply a field by shape functions @f$ fts_{ij} = f_i * \varphi_j @f$ template <ElementType type> void fieldTimesShapes(const Array<Real> & field, Array<Real> & field_times_shapes, GhostType ghost_type) const; /// find natural coords from real coords provided an element template <ElementType type> void inverseMap(const Vector<Real> & real_coords, UInt element, Vector<Real> & natural_coords, const GhostType & ghost_type = _not_ghost) const; /// return true if the coordinates provided are inside the element, false /// otherwise template <ElementType type> bool contains(const Vector<Real> & real_coords, UInt elem, const GhostType & ghost_type) const; /// compute the shape on a provided point template <ElementType type> void computeShapes(const Vector<Real> & real_coords, UInt elem, Vector<Real> & shapes, const GhostType & ghost_type) const; /// compute the shape derivatives on a provided point template <ElementType type> void computeShapeDerivatives(const Matrix<Real> & real_coords, UInt elem, Tensor3<Real> & shapes, const GhostType & ghost_type) const; /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; protected: /// compute the shape derivatives on integration points for a given element template <ElementType type> inline void computeShapeDerivativesOnCPointsByElement(const Matrix<Real> & node_coords, const Matrix<Real> & natural_coords, Tensor3<Real> & shapesd) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get a the shapes vector inline const Array<Real> & getShapes(const ElementType & el_type, const GhostType & ghost_type = _not_ghost) const; /// get a the shapes derivatives vector inline const Array<Real> & getShapesDerivatives(const ElementType & el_type, const GhostType & ghost_type = _not_ghost) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// shape functions for all elements ElementTypeMapArray<Real, InterpolationType> shapes; /// shape functions derivatives for all elements ElementTypeMapArray<Real, InterpolationType> shapes_derivatives; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "shape_lagrange_inline_impl.cc" -__END_AKANTU__ +} // akantu #endif /* __AKANTU_SHAPE_LAGRANGE_HH__ */ diff --git a/src/fe_engine/shape_lagrange_inline_impl.cc b/src/fe_engine/shape_lagrange_inline_impl.cc index 27a13d4f8..a2812bd96 100644 --- a/src/fe_engine/shape_lagrange_inline_impl.cc +++ b/src/fe_engine/shape_lagrange_inline_impl.cc @@ -1,466 +1,466 @@ /** * @file shape_lagrange_inline_impl.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Oct 27 2010 * @date last modification: Thu Oct 15 2015 * * @brief ShapeLagrange inline implementation * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ -__END_AKANTU__ +} // akantu #include "fe_engine.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <ElementKind kind> inline const Array<Real> & ShapeLagrange<kind>::getShapes(const ElementType & el_type, const GhostType & ghost_type) const { return shapes(FEEngine::getInterpolationType(el_type), ghost_type); } /* -------------------------------------------------------------------------- */ template <ElementKind kind> inline const Array<Real> & ShapeLagrange<kind>::getShapesDerivatives(const ElementType & el_type, const GhostType & ghost_type) const { return shapes_derivatives(FEEngine::getInterpolationType(el_type), ghost_type); } /* -------------------------------------------------------------------------- */ #define INIT_SHAPE_FUNCTIONS(type) \ setIntegrationPointsByType<type>(integration_points, ghost_type); \ precomputeShapesOnIntegrationPoints<type>(nodes, ghost_type); \ if (ElementClass<type>::getNaturalSpaceDimension() == \ mesh.getSpatialDimension() || \ kind != _ek_regular) \ precomputeShapeDerivativesOnIntegrationPoints<type>(nodes, ghost_type); template <ElementKind kind> inline void ShapeLagrange<kind>::initShapeFunctions( const Array<Real> & nodes, const Matrix<Real> & integration_points, const ElementType & type, const GhostType & ghost_type) { AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(INIT_SHAPE_FUNCTIONS); } #if defined(AKANTU_STRUCTURAL_MECHANICS) /* -------------------------------------------------------------------------- */ template <> inline void ShapeLagrange<_ek_structural>::initShapeFunctions( __attribute__((unused)) const Array<Real> & nodes, __attribute__((unused)) const Matrix<Real> & integration_points, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); } #endif #undef INIT_SHAPE_FUNCTIONS /* -------------------------------------------------------------------------- */ template <ElementKind kind> template <ElementType type> inline void ShapeLagrange<kind>::computeShapeDerivativesOnCPointsByElement( const Matrix<Real> & node_coords, const Matrix<Real> & natural_coords, Tensor3<Real> & shapesd) const { AKANTU_DEBUG_IN(); // compute dnds Tensor3<Real> dnds(node_coords.rows(), node_coords.cols(), natural_coords.cols()); ElementClass<type>::computeDNDS(natural_coords, dnds); // compute dxds Tensor3<Real> J(node_coords.rows(), natural_coords.rows(), natural_coords.cols()); ElementClass<type>::computeJMat(dnds, node_coords, J); // compute shape derivatives ElementClass<type>::computeShapeDerivatives(J, dnds, shapesd); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind> template <ElementType type> void ShapeLagrange<kind>::inverseMap(const Vector<Real> & real_coords, UInt elem, Vector<Real> & natural_coords, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes_per_element = ElementClass<type>::getNbNodesPerInterpolationElement(); UInt * elem_val = mesh.getConnectivity(type, ghost_type).storage(); Matrix<Real> nodes_coord(spatial_dimension, nb_nodes_per_element); mesh.extractNodalValuesFromElement(mesh.getNodes(), nodes_coord.storage(), elem_val + elem * nb_nodes_per_element, nb_nodes_per_element, spatial_dimension); ElementClass<type>::inverseMap(real_coords, nodes_coord, natural_coords); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind> template <ElementType type> bool ShapeLagrange<kind>::contains(const Vector<Real> & real_coords, UInt elem, const GhostType & ghost_type) const { UInt spatial_dimension = mesh.getSpatialDimension(); Vector<Real> natural_coords(spatial_dimension); inverseMap<type>(real_coords, elem, natural_coords, ghost_type); return ElementClass<type>::contains(natural_coords); } /* -------------------------------------------------------------------------- */ template <ElementKind kind> template <ElementType type> void ShapeLagrange<kind>::interpolate(const Vector<Real> & real_coords, UInt elem, const Matrix<Real> & nodal_values, Vector<Real> & interpolated, const GhostType & ghost_type) const { UInt nb_shapes = ElementClass<type>::getShapeSize(); Vector<Real> shapes(nb_shapes); computeShapes<type>(real_coords, elem, shapes, ghost_type); ElementClass<type>::interpolate(nodal_values, shapes, interpolated); } /* -------------------------------------------------------------------------- */ template <ElementKind kind> template <ElementType type> void ShapeLagrange<kind>::computeShapes(const Vector<Real> & real_coords, UInt elem, Vector<Real> & shapes, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); Vector<Real> natural_coords(spatial_dimension); inverseMap<type>(real_coords, elem, natural_coords, ghost_type); ElementClass<type>::computeShapes(natural_coords, shapes); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind> template <ElementType type> void ShapeLagrange<kind>::computeShapeDerivatives( const Matrix<Real> & real_coords, UInt elem, Tensor3<Real> & shapesd, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt nb_points = real_coords.cols(); UInt nb_nodes_per_element = ElementClass<type>::getNbNodesPerInterpolationElement(); AKANTU_DEBUG_ASSERT(mesh.getSpatialDimension() == shapesd.size(0) && nb_nodes_per_element == shapesd.size(1), "Shape size doesn't match"); AKANTU_DEBUG_ASSERT(nb_points == shapesd.size(2), "Number of points doesn't match shapes size"); Matrix<Real> natural_coords(spatial_dimension, nb_points); // Creates the matrix of natural coordinates for (UInt i = 0; i < nb_points; i++) { Vector<Real> real_point = real_coords(i); Vector<Real> natural_point = natural_coords(i); inverseMap<type>(real_point, elem, natural_point, ghost_type); } UInt * elem_val = mesh.getConnectivity(type, ghost_type).storage(); Matrix<Real> nodes_coord(spatial_dimension, nb_nodes_per_element); mesh.extractNodalValuesFromElement(mesh.getNodes(), nodes_coord.storage(), elem_val + elem * nb_nodes_per_element, nb_nodes_per_element, spatial_dimension); computeShapeDerivativesOnCPointsByElement<type>(nodes_coord, natural_coords, shapesd); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind> ShapeLagrange<kind>::ShapeLagrange(const Mesh & mesh, const ID & id, const MemoryID & memory_id) : ShapeFunctions(mesh, id, memory_id), shapes("shapes_generic", id, memory_id), shapes_derivatives("shapes_derivatives_generic", id, memory_id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind> template <ElementType type> void ShapeLagrange<kind>::computeShapesOnIntegrationPoints( __attribute__((unused)) const Array<Real> & nodes, const Matrix<Real> & integration_points, Array<Real> & shapes, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt nb_points = integration_points.cols(); UInt nb_element = mesh.getConnectivity(type, ghost_type).getSize(); shapes.resize(nb_element * nb_points); #if !defined(AKANTU_NDEBUG) UInt size_of_shapes = ElementClass<type>::getShapeSize(); AKANTU_DEBUG_ASSERT(shapes.getNbComponent() == size_of_shapes, "The shapes array does not have the correct " << "number of component"); #endif Array<Real>::matrix_iterator shapes_it = shapes.begin_reinterpret( ElementClass<type>::getNbNodesPerInterpolationElement(), nb_points, nb_element); for (UInt elem = 0; elem < nb_element; ++elem, ++shapes_it) { Matrix<Real> & N = *shapes_it; ElementClass<type>::computeShapes(integration_points, N); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind> template <ElementType type> void ShapeLagrange<kind>::precomputeShapesOnIntegrationPoints( const Array<Real> & nodes, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); InterpolationType itp_type = ElementClassProperty<type>::interpolation_type; Matrix<Real> & natural_coords = integration_points(type, ghost_type); UInt size_of_shapes = ElementClass<type>::getShapeSize(); Array<Real> & shapes_tmp = shapes.alloc(0, size_of_shapes, itp_type, ghost_type); this->computeShapesOnIntegrationPoints<type>(nodes, natural_coords, shapes_tmp, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind> template <ElementType type> void ShapeLagrange<kind>::computeShapeDerivativesOnIntegrationPoints( const Array<Real> & nodes, const Matrix<Real> & integration_points, Array<Real> & shape_derivatives, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes_per_element = ElementClass<type>::getNbNodesPerInterpolationElement(); UInt nb_points = integration_points.cols(); UInt nb_element = mesh.getConnectivity(type, ghost_type).getSize(); UInt size_of_shapesd = ElementClass<type>::getShapeDerivativesSize(); AKANTU_DEBUG_ASSERT(shape_derivatives.getNbComponent() == size_of_shapesd, "The shapes_derivatives array does not have the correct " << "number of component"); shape_derivatives.resize(nb_element * nb_points); Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element); FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type); Real * shapesd_val = shape_derivatives.storage(); Array<Real>::matrix_iterator x_it = x_el.begin(spatial_dimension, nb_nodes_per_element); for (UInt elem = 0; elem < nb_element; ++elem, ++x_it) { Matrix<Real> & X = *x_it; Tensor3<Real> B(shapesd_val, spatial_dimension, nb_nodes_per_element, nb_points); computeShapeDerivativesOnCPointsByElement<type>(X, integration_points, B); shapesd_val += size_of_shapesd * nb_points; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind> template <ElementType type> void ShapeLagrange<kind>::precomputeShapeDerivativesOnIntegrationPoints( const Array<Real> & nodes, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); Matrix<Real> & natural_coords = integration_points(type, ghost_type); InterpolationType itp_type = ElementClassProperty<type>::interpolation_type; UInt size_of_shapesd = ElementClass<type>::getShapeDerivativesSize(); Array<Real> & shapes_derivatives_tmp = shapes_derivatives.alloc(0, size_of_shapesd, itp_type, ghost_type); this->computeShapeDerivativesOnIntegrationPoints<type>( nodes, natural_coords, shapes_derivatives_tmp, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template <ElementKind kind> template <ElementType type> void ShapeLagrange<kind>::interpolateOnIntegrationPoints( const Array<Real> & in_u, Array<Real> & out_uq, UInt nb_degree_of_freedom, const Array<Real> & shapes, GhostType ghost_type, const Array<UInt> & filter_elements) const { AKANTU_DEBUG_IN(); UInt nb_nodes_per_element = ElementClass<type>::getNbNodesPerInterpolationElement(); Array<Real> u_el(0, nb_degree_of_freedom * nb_nodes_per_element); FEEngine::extractNodalToElementField(mesh, in_u, u_el, type, ghost_type, filter_elements); this->interpolateElementalFieldOnIntegrationPoints<type>( u_el, out_uq, ghost_type, shapes, filter_elements); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind> template <ElementType type> void ShapeLagrange<kind>::interpolateOnIntegrationPoints( const Array<Real> & in_u, Array<Real> & out_uq, UInt nb_degree_of_freedom, GhostType ghost_type, const Array<UInt> & filter_elements) const { AKANTU_DEBUG_IN(); InterpolationType itp_type = ElementClassProperty<type>::interpolation_type; AKANTU_DEBUG_ASSERT(shapes.exists(itp_type, ghost_type), "No shapes for the type " << shapes.printType(itp_type, ghost_type)); this->interpolateOnIntegrationPoints<type>(in_u, out_uq, nb_degree_of_freedom, shapes(itp_type, ghost_type), ghost_type, filter_elements); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind> template <ElementType type> void ShapeLagrange<kind>::gradientOnIntegrationPoints( const Array<Real> & in_u, Array<Real> & out_nablauq, UInt nb_degree_of_freedom, GhostType ghost_type, const Array<UInt> & filter_elements) const { AKANTU_DEBUG_IN(); InterpolationType itp_type = ElementClassProperty<type>::interpolation_type; AKANTU_DEBUG_ASSERT( shapes_derivatives.exists(itp_type, ghost_type), "No shapes derivatives for the type " << shapes_derivatives.printType(itp_type, ghost_type)); UInt nb_nodes_per_element = ElementClass<type>::getNbNodesPerInterpolationElement(); Array<Real> u_el(0, nb_degree_of_freedom * nb_nodes_per_element); FEEngine::extractNodalToElementField(mesh, in_u, u_el, type, ghost_type, filter_elements); this->gradientElementalFieldOnIntegrationPoints<type>( u_el, out_nablauq, ghost_type, shapes_derivatives(itp_type, ghost_type), filter_elements); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind> template <ElementType type> void ShapeLagrange<kind>::fieldTimesShapes(const Array<Real> & field, Array<Real> & field_times_shapes, GhostType ghost_type) const { AKANTU_DEBUG_IN(); field_times_shapes.resize(field.getSize()); UInt size_of_shapes = ElementClass<type>::getShapeSize(); InterpolationType itp_type = ElementClassProperty<type>::interpolation_type; UInt nb_degree_of_freedom = field.getNbComponent(); const Array<Real> & shape = shapes(itp_type, ghost_type); Array<Real>::const_matrix_iterator field_it = field.begin(nb_degree_of_freedom, 1); Array<Real>::const_matrix_iterator shapes_it = shape.begin(1, size_of_shapes); Array<Real>::matrix_iterator it = field_times_shapes.begin(nb_degree_of_freedom, size_of_shapes); Array<Real>::matrix_iterator end = field_times_shapes.end(nb_degree_of_freedom, size_of_shapes); for (; it != end; ++it, ++field_it, ++shapes_it) { it->mul<false, false>(*field_it, *shapes_it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementKind kind> void ShapeLagrange<kind>::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; ShapeFunctions::printself(stream, indent + 1); shapes.printself(stream, indent + 1); shapes_derivatives.printself(stream, indent + 1); stream << space << "]" << std::endl; } diff --git a/src/fe_engine/shape_linked.cc b/src/fe_engine/shape_linked.cc index eb5f8eaa1..86392fec7 100644 --- a/src/fe_engine/shape_linked.cc +++ b/src/fe_engine/shape_linked.cc @@ -1,82 +1,82 @@ /** * @file shape_linked.cc * * @author Fabian Barras <fabian.barras@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jul 15 2011 * @date last modification: Sun Oct 19 2014 * * @brief ShapeLinked implementation * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" #include "mesh.hh" #include "shape_linked.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { #if defined(AKANTU_STRUCTURAL_MECHANICS) /* -------------------------------------------------------------------------- */ template <> ShapeLinked<_ek_structural>::ShapeLinked(Mesh & mesh, const ID & id, const MemoryID & memory_id) : ShapeFunctions(mesh, id, memory_id) { } /* -------------------------------------------------------------------------- */ template <> ShapeLinked<_ek_structural>::~ShapeLinked() { for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; // delete all the shapes id ElementTypeMapMultiReal::type_iterator s_type_it = shapes.firstType(_all_dimensions, ghost_type, _ek_structural); ElementTypeMapMultiReal::type_iterator s_type_end = shapes.lastType (_all_dimensions, ghost_type, _ek_structural); for(; s_type_it != s_type_end; ++s_type_it) { delete [] shapes(*s_type_it, ghost_type); } // delete all the shapes derivatives id ElementTypeMapMultiReal::type_iterator sd_type_it = shapes_derivatives.firstType(_all_dimensions, ghost_type, _ek_structural); ElementTypeMapMultiReal::type_iterator sd_type_end = shapes_derivatives.lastType (_all_dimensions, ghost_type, _ek_structural); for(; sd_type_it != sd_type_end; ++sd_type_it) { delete [] shapes_derivatives(*sd_type_it, ghost_type); } } } #endif -__END_AKANTU__ +} // akantu diff --git a/src/fe_engine/shape_linked.hh b/src/fe_engine/shape_linked.hh index 48dc59731..1e0c6eae5 100644 --- a/src/fe_engine/shape_linked.hh +++ b/src/fe_engine/shape_linked.hh @@ -1,161 +1,161 @@ /** * @file shape_linked.hh * * @author Fabian Barras <fabian.barras@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Feb 15 2011 * @date last modification: Thu Oct 22 2015 * * @brief shape class for element with different set of shapes functions * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "shape_functions.hh" #ifndef __AKANTU_SHAPE_LINKED_HH__ #define __AKANTU_SHAPE_LINKED_HH__ -__BEGIN_AKANTU__ +namespace akantu { template <ElementKind kind> class ShapeLinked : public ShapeFunctions { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef ElementTypeMap<Array<Real> **> ElementTypeMapMultiReal; ShapeLinked(Mesh & mesh, const ID & id = "shape_linked", const MemoryID & memory_id = 0); virtual ~ShapeLinked(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialization function for structural elements inline void initShapeFunctions(const Array<Real> & nodes, const Matrix<Real> & integration_points, const ElementType & type, const GhostType & ghost_type); /// pre compute all shapes on the element integration points from natural coordinates template <ElementType type> void precomputeShapesOnIntegrationPoints(const Array<Real> & nodes, const GhostType & ghost_type); /// pre compute all shapes on the element integration points from natural coordinates template <ElementType type> void precomputeShapeDerivativesOnIntegrationPoints(const Array<Real> & nodes, const GhostType & ghost_type); /// interpolate nodal values on the integration points template <ElementType type> void interpolateOnIntegrationPoints(const Array<Real> &u, Array<Real> &uq, UInt nb_degree_of_freedom, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter, bool accumulate = false, UInt id_shape = 0, UInt num_degre_of_freedom_to_interpolate = 0, UInt num_degre_of_freedom_interpolated = 0) const; /// compute the gradient of u on the integration points template <ElementType type> void gradientOnIntegrationPoints(const Array<Real> &u, Array<Real> &nablauq, UInt nb_degree_of_freedom, const GhostType & ghost_type = _not_ghost, const Array<UInt> & filter_elements = empty_filter, bool accumulate = false, UInt id_shape = 0, UInt num_degre_of_freedom_to_interpolate = 0, UInt num_degre_of_freedom_interpolated = 0) const; /// multiply a field by shape functions template <ElementType type> void fieldTimesShapes(__attribute__((unused)) const Array<Real> & field, __attribute__((unused)) Array<Real> & fiedl_times_shapes, __attribute__((unused)) const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); } private: /// extract the nodal field value to fill an elemental field template <ElementType type> void extractNodalToElementField(const Array<Real> & nodal_f, Array<Real> & elemental_f, UInt num_degre_of_freedom_to_extract, const GhostType & ghost_type, const Array<UInt> & filter_elements) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get a the shapes vector inline const Array<Real> & getShapes(const ElementType & type, const GhostType & ghost_type, UInt id = 0) const; /// get a the shapes derivatives vector inline const Array<Real> & getShapesDerivatives(const ElementType & type, const GhostType & ghost_type, UInt id = 0) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// shape functions for all elements ElementTypeMapMultiReal shapes; /// shape derivatives for all elements ElementTypeMapMultiReal shapes_derivatives; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "shape_linked_inline_impl.cc" #endif /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const ShapeLinked & _this) // { // _this.printself(stream); // return stream; // } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_SHAPE_LINKED_HH__ */ diff --git a/src/geometry/aabb_primitives/aabb_primitive.cc b/src/geometry/aabb_primitives/aabb_primitive.cc index 3a511c8bc..3470de999 100644 --- a/src/geometry/aabb_primitives/aabb_primitive.cc +++ b/src/geometry/aabb_primitives/aabb_primitive.cc @@ -1,49 +1,49 @@ /** * @file aabb_primitive.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Clement Roux <clement.roux@epfl.ch> * * @date creation: Fri Jan 04 2013 * @date last modification: Thu Jan 14 2016 * * @brief Macro classe (primitive) for AABB CGAL algos * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aabb_primitive.hh" -__BEGIN_AKANTU__ +namespace akantu { Triangle_primitive::Point Triangle_primitive::reference_point() const { return primitive.vertex(0); } Line_arc_primitive::Point Line_arc_primitive::reference_point() const { Real x = to_double(primitive.source().x()); Real y = to_double(primitive.source().y()); Real z = to_double(primitive.source().z()); return Spherical::Point_3(x, y, z); } -__END_AKANTU__ +} // akantu diff --git a/src/geometry/aabb_primitives/aabb_primitive.hh b/src/geometry/aabb_primitives/aabb_primitive.hh index aadefaf24..4a9a9f506 100644 --- a/src/geometry/aabb_primitives/aabb_primitive.hh +++ b/src/geometry/aabb_primitives/aabb_primitive.hh @@ -1,90 +1,90 @@ /** * @file aabb_primitive.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Clement Roux <clement.roux@epfl.ch> * * @date creation: Fri Mar 13 2015 * @date last modification: Thu Jan 14 2016 * * @brief Macro classe (primitive) for AABB CGAL algos * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AABB_PRIMITIVE_HH__ #define __AKANTU_AABB_PRIMITIVE_HH__ #include "aka_common.hh" #include "line_arc.hh" #include "triangle.hh" #include "tetrahedron.hh" #include "mesh_geom_common.hh" -__BEGIN_AKANTU__ +namespace akantu { /** * This macro defines a class that is used in the CGAL AABB tree algorithm. * All the `typedef`s and methods are required by the AABB module. * * The member variables are * - the id of the element associated to the primitive * - the geometric primitive of the element * * @param name the name of the primitive type * @param kernel the name of the kernel used */ #define AKANTU_AABB_CLASS(name, kernel) \ class name##_primitive { \ typedef std::list< name<kernel> >::iterator Iterator; \ \ public: \ typedef UInt Id; \ typedef kernel::Point_3 Point; \ typedef kernel::name##_3 Datum; \ \ public: \ name##_primitive() : meshId(0), primitive() {} \ name##_primitive(Iterator it) : meshId(it->id()), primitive(*it) {} \ \ public: \ const Datum & datum() const { return primitive; } \ Point reference_point() const; \ const Id & id() const { return meshId; } \ \ protected: \ Id meshId; \ name<kernel> primitive; \ \ } // If the primitive is supported by CGAL::intersection() then the // implementation process is really easy with this macro AKANTU_AABB_CLASS(Triangle, Cartesian); AKANTU_AABB_CLASS(Line_arc, Spherical); #undef AKANTU_AABB_CLASS -__END_AKANTU__ +} // akantu #endif // __AKANTU_AABB_PRIMITIVE_HH__ diff --git a/src/geometry/aabb_primitives/line_arc.hh b/src/geometry/aabb_primitives/line_arc.hh index 71bcd5d09..409cc91d8 100644 --- a/src/geometry/aabb_primitives/line_arc.hh +++ b/src/geometry/aabb_primitives/line_arc.hh @@ -1,78 +1,78 @@ /** * @file line_arc.hh * * @author Clement Roux <clement.roux@epfl.ch> * * @date creation: Fri Jan 04 2013 * @date last modification: Thu Jan 14 2016 * * @brief Segment classe (geometry) for AABB CGAL algos * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_LINE_ARC_HH__ #define __AKANTU_LINE_ARC_HH__ #include "aka_common.hh" #include "mesh_geom_common.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /// Class used for substitution of CGAL::Triangle_3 primitive template<typename K> class Line_arc : public CGAL::Line_arc_3<K> { public: /// Default constructor Line_arc() : CGAL::Line_arc_3<K>(), mesh_id(0), seg_id(0) {} /// Copy constructor Line_arc(const Line_arc & other) : CGAL::Line_arc_3<K>(other), mesh_id(other.mesh_id), seg_id(other.seg_id) {} /// Construct from 3 points // "CGAL-4.5/doc_html/Circular_kernel_3/classCGAL_1_1Line__arc__3.html" Line_arc(const CGAL::Line_3<K> & l, const CGAL::Circular_arc_point_3<K> & a, const CGAL::Circular_arc_point_3<K> & b): CGAL::Line_arc_3<K>(l, a, b), mesh_id(0), seg_id(0) {} public: UInt id() const { return mesh_id; } UInt segId() const { return seg_id; } void setId(UInt newId) { mesh_id = newId; } void setSegId(UInt newId) { seg_id = newId; } protected: /// Id of the element represented by the primitive UInt mesh_id; /// Id of the segment represented by the primitive UInt seg_id; }; -__END_AKANTU__ +} // akantu #endif // __AKANTU_LINE_ARC_HH__ diff --git a/src/geometry/aabb_primitives/tetrahedron.hh b/src/geometry/aabb_primitives/tetrahedron.hh index cc309ba07..daf0d4145 100644 --- a/src/geometry/aabb_primitives/tetrahedron.hh +++ b/src/geometry/aabb_primitives/tetrahedron.hh @@ -1,74 +1,74 @@ /** * @file tetrahedron.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Fri Feb 27 2015 * @date last modification: Thu Jan 14 2016 * * @brief Tetrahedron classe (geometry) for AABB CGAL algos * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_TETRAHEDRON_HH__ #define __AKANTU_TETRAHEDRON_HH__ #include "aka_common.hh" #include "mesh_geom_common.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /// Class used for substitution of CGAL::Tetrahedron_3 primitive template<typename K> class Tetrahedron : public CGAL::Tetrahedron_3<K> { public: /// Default constructor Tetrahedron() : CGAL::Tetrahedron_3<K>(), meshId(0) {} /// Copy constructor Tetrahedron(const Tetrahedron & other) : CGAL::Tetrahedron_3<K>(other), meshId(other.meshId) {} /// Construct from 4 points Tetrahedron(const CGAL::Point_3<K> & a, const CGAL::Point_3<K> & b, const CGAL::Point_3<K> & c, const CGAL::Point_3<K> & d) : CGAL::Tetrahedron_3<K>(a, b, c, d), meshId(0) {} public: UInt id() const { return meshId; } void setId(UInt newId) { meshId = newId; } protected: /// Id of the element represented by the primitive UInt meshId; }; -__END_AKANTU__ +} // akantu #endif diff --git a/src/geometry/aabb_primitives/triangle.hh b/src/geometry/aabb_primitives/triangle.hh index 9243e73d0..d25912af9 100644 --- a/src/geometry/aabb_primitives/triangle.hh +++ b/src/geometry/aabb_primitives/triangle.hh @@ -1,71 +1,71 @@ /** * @file triangle.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Fri Jan 04 2013 * @date last modification: Thu Jan 14 2016 * * @brief Triangle classe (geometry) for AABB CGAL algos * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_TRIANGLE_HH__ #define __AKANTU_TRIANGLE_HH__ #include "aka_common.hh" #include "mesh_geom_common.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /// Class used for substitution of CGAL::Triangle_3 primitive template<typename K> class Triangle : public CGAL::Triangle_3<K> { public: /// Default constructor Triangle() : CGAL::Triangle_3<K>(), meshId(0) {} /// Copy constructor Triangle(const Triangle & other) : CGAL::Triangle_3<K>(other), meshId(other.meshId) {} /// Construct from 3 points Triangle(const CGAL::Point_3<K> & a, const CGAL::Point_3<K> & b, const CGAL::Point_3<K> & c): CGAL::Triangle_3<K>(a, b, c), meshId(0) {} public: UInt id() const { return meshId; } void setId(UInt newId) { meshId = newId; } protected: /// Id of the element represented by the primitive UInt meshId; }; -__END_AKANTU__ +} // akantu #endif // __AKANTU_TRIANGLE_HH__ diff --git a/src/geometry/geom_helper_functions.hh b/src/geometry/geom_helper_functions.hh index fbe6bbaca..14e933bf3 100644 --- a/src/geometry/geom_helper_functions.hh +++ b/src/geometry/geom_helper_functions.hh @@ -1,104 +1,104 @@ /** * @file geom_helper_functions.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Clement Roux <clement.roux@epfl.ch> * * @date creation: Fri Jan 04 2013 * @date last modification: Thu Jan 14 2016 * * @brief Helper functions for the computational geometry algorithms * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef _AKANTU_GEOM_HELPER_FUNCTIONS_HH__ #define _AKANTU_GEOM_HELPER_FUNCTIONS_HH__ #include "aka_common.hh" #include "aka_math.hh" #include "tree_type_helper.hh" #include "mesh_geom_common.hh" -__BEGIN_AKANTU__ +namespace akantu { /// Fuzzy compare of two points template <class Point> inline bool comparePoints(const Point & a, const Point & b) { return Math::are_float_equal(a.x(), b.x()) && Math::are_float_equal(a.y(), b.y()) && Math::are_float_equal(a.z(), b.z()); } template <> inline bool comparePoints(const Spherical::Circular_arc_point_3 & a, const Spherical::Circular_arc_point_3 & b) { return Math::are_float_equal(CGAL::to_double(a.x()), CGAL::to_double(b.x())) && Math::are_float_equal(CGAL::to_double(a.y()), CGAL::to_double(b.y())) && Math::are_float_equal(CGAL::to_double(a.z()), CGAL::to_double(b.z())); } /// Fuzzy compare of two segments template <class K> inline bool compareSegments(const CGAL::Segment_3<K> & a, const CGAL::Segment_3<K> & b) { return (comparePoints(a.source(), b.source()) && comparePoints(a.target(), b.target())) || (comparePoints(a.source(), b.target()) && comparePoints(a.target(), b.source())); } typedef Cartesian K; /// Compare segment pairs inline bool compareSegmentPairs(const std::pair<K::Segment_3, UInt> & a, const std::pair<K::Segment_3, UInt> & b) { return compareSegments(a.first, b.first); } /// Pair ordering operator based on first member struct segmentPairsLess { inline bool operator()(const std::pair<K::Segment_3, UInt> & a, const std::pair<K::Segment_3, UInt> & b) { return CGAL::compare_lexicographically(a.first.min(), b.first.min()) || CGAL::compare_lexicographically(a.first.max(), b.first.max()); } }; /* -------------------------------------------------------------------------- */ /* Predicates */ /* -------------------------------------------------------------------------- */ /// Predicate used to determine if two segments are equal class IsSameSegment { public: IsSameSegment(const K::Segment_3 & segment): segment(segment) {} bool operator()(const std::pair<K::Segment_3, UInt> & test_pair) { return compareSegments(segment, test_pair.first); } protected: const K::Segment_3 segment; }; -__END_AKANTU__ +} // akantu #endif // _AKANTU_GEOM_HELPER_FUNCTIONS_HH__ diff --git a/src/geometry/mesh_abstract_intersector.hh b/src/geometry/mesh_abstract_intersector.hh index b69beb764..6c1222924 100644 --- a/src/geometry/mesh_abstract_intersector.hh +++ b/src/geometry/mesh_abstract_intersector.hh @@ -1,108 +1,108 @@ /** * @file mesh_abstract_intersector.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Clement Roux <clement.roux@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Apr 29 2015 * @date last modification: Thu Jan 14 2016 * * @brief Abstract class for intersection computations * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_ABSTRACT_INTERSECTOR_HH__ #define __AKANTU_MESH_ABSTRACT_INTERSECTOR_HH__ #include "aka_common.hh" #include "mesh_geom_abstract.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /** * @brief Class used to perform intersections on a mesh and construct output data */ template<class Query> class MeshAbstractIntersector : public MeshGeomAbstract { public: /// Construct from mesh explicit MeshAbstractIntersector(Mesh & mesh); /// Destructor virtual ~MeshAbstractIntersector(); public: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the new_node_per_elem array AKANTU_GET_MACRO(NewNodePerElem, *new_node_per_elem, const Array<UInt> &); /// get the intersection_points array AKANTU_GET_MACRO(IntersectionPoints, intersection_points, const Array<Real> *); /// get the nb_seg_by_el UInt AKANTU_GET_MACRO(NbSegByEl, nb_seg_by_el, UInt); /** * @brief Compute the intersection with a query object * * This function needs to be implemented for every subclass. It computes the intersections * with the tree of primitives and creates the data for the user. * * @param query the CGAL primitive of the query object */ virtual void computeIntersectionQuery(const Query & query) = 0; /// Compute intersection points between the mesh primitives (segments) and a query (surface in 3D or a curve in 2D), double intersection points for the same primitives are not considered. A maximum intersection node per element is set : 2 in 2D and 4 in 3D virtual void computeMeshQueryIntersectionPoint(const Query & query, UInt nb_old_nodes) = 0; /// Compute intersection between the mesh and a list of queries virtual void computeIntersectionQueryList(const std::list<Query> & query_list); /// Compute intersection points between the mesh and a list of queries virtual void computeMeshQueryListIntersectionPoint(const std::list<Query> & query_list, UInt nb_old_nodes); /// Compute whatever result is needed from the user (should be move to the appropriate specific classe for genericity) virtual void buildResultFromQueryList(const std::list<Query> & query_list) = 0; protected: /// new node per element (column 0: number of new nodes, then odd is the intersection node number and even the ID of the intersected segment) Array<UInt> * new_node_per_elem; /// intersection output: new intersection points (computeMeshQueryListIntersectionPoint) Array<Real> * intersection_points; /// number of segment in a considered element of the templated type of element specialized intersector const UInt nb_seg_by_el; }; -__END_AKANTU__ +} // akantu #include "mesh_abstract_intersector_tmpl.hh" #endif // __AKANTU_MESH_ABSTRACT_INTERSECTOR_HH__ diff --git a/src/geometry/mesh_abstract_intersector_tmpl.hh b/src/geometry/mesh_abstract_intersector_tmpl.hh index 9782cee04..6d4b4d75f 100644 --- a/src/geometry/mesh_abstract_intersector_tmpl.hh +++ b/src/geometry/mesh_abstract_intersector_tmpl.hh @@ -1,89 +1,89 @@ /** * @file mesh_abstract_intersector_tmpl.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Clement Roux <clement.roux@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Apr 29 2015 * @date last modification: Thu Jan 14 2016 * * @brief General class for intersection computations * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_ABSTRACT_INTERSECTOR_TMPL_HH__ #define __AKANTU_MESH_ABSTRACT_INTERSECTOR_TMPL_HH__ #include "aka_common.hh" #include "mesh_abstract_intersector.hh" -__BEGIN_AKANTU__ +namespace akantu { template<class Query> MeshAbstractIntersector<Query>::MeshAbstractIntersector(Mesh & mesh): MeshGeomAbstract(mesh), new_node_per_elem(NULL), intersection_points(NULL), nb_seg_by_el(0) {} template<class Query> MeshAbstractIntersector<Query>::~MeshAbstractIntersector() {} template<class Query> void MeshAbstractIntersector<Query>::computeIntersectionQueryList( const std::list<Query> & query_list) { AKANTU_DEBUG_IN(); typename std::list<Query>::const_iterator query_it = query_list.begin(), query_end = query_list.end(); for (; query_it != query_end ; ++query_it) { computeIntersectionQuery(*query_it); } AKANTU_DEBUG_OUT(); } template<class Query> void MeshAbstractIntersector<Query>::computeMeshQueryListIntersectionPoint( const std::list<Query> & query_list, UInt nb_old_nodes) { AKANTU_DEBUG_IN(); typename std::list<Query>::const_iterator query_it = query_list.begin(), query_end = query_list.end(); for (; query_it != query_end ; ++query_it) { computeMeshQueryIntersectionPoint(*query_it, nb_old_nodes); } AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu #endif // __AKANTU_MESH_ABSTRACT_INTERSECTOR_TMPL_HH__ diff --git a/src/geometry/mesh_geom_abstract.hh b/src/geometry/mesh_geom_abstract.hh index 9ab8ff286..a3b2f39b0 100644 --- a/src/geometry/mesh_geom_abstract.hh +++ b/src/geometry/mesh_geom_abstract.hh @@ -1,65 +1,65 @@ /** * @file mesh_geom_abstract.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jan 04 2013 * @date last modification: Thu Jan 14 2016 * * @brief Class for constructing the CGAL primitives of a mesh * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_GEOM_ABSTRACT_HH__ #define __AKANTU_MESH_GEOM_ABSTRACT_HH__ #include "aka_common.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /// Abstract class for mesh geometry operations class MeshGeomAbstract { public: /// Construct from mesh explicit MeshGeomAbstract(Mesh & mesh) : mesh(mesh) {}; /// Destructor virtual ~MeshGeomAbstract() {}; public: /// Construct geometric data for computational geometry algorithms virtual void constructData(GhostType ghost_type = _not_ghost) = 0; protected: /// Mesh used to construct the primitives Mesh & mesh; }; -__END_AKANTU__ +} // akantu #endif // __AKANTU_MESH_GEOM_ABSTRACT_HH__ diff --git a/src/geometry/mesh_geom_common.hh b/src/geometry/mesh_geom_common.hh index c326329bc..72289b9c9 100644 --- a/src/geometry/mesh_geom_common.hh +++ b/src/geometry/mesh_geom_common.hh @@ -1,58 +1,58 @@ /** * @file mesh_geom_common.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Clement Roux <clement.roux@epfl.ch> * * @date creation: Fri Jan 04 2013 * @date last modification: Thu Jan 14 2016 * * @brief Common file for MeshGeom module * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_MESH_GEOM_COMMON_HH__ #define __AKANTU_MESH_GEOM_COMMON_HH__ #include "aka_common.hh" #include <CGAL/MP_Float.h> #include <CGAL/Quotient.h> #include <CGAL/Cartesian.h> #include <CGAL/Simple_cartesian.h> #include <CGAL/Spherical_kernel_3.h> #include <CGAL/Algebraic_kernel_for_spheres_2_3.h> #include <CGAL/Lazy_exact_nt.h> -__BEGIN_AKANTU__ +namespace akantu { typedef CGAL::Simple_cartesian<Real> Cartesian; typedef CGAL::Quotient<CGAL::MP_Float> NT; typedef CGAL::Spherical_kernel_3<CGAL::Simple_cartesian<NT>, CGAL::Algebraic_kernel_for_spheres_2_3<NT> > Spherical; //typedef CGAL::Lazy_exact_nt<CGAL::Quotient<CGAL::MP_Float> > NT; //typedef CGAL::Spherical_kernel_3<CGAL::Simple_cartesian<NT>, CGAL::Algebraic_kernel_for_spheres_2_3<NT> > Spherical; -__END_AKANTU__ +} // akantu #endif // __AKANTU_MESH_GEOM_COMMON_HH__ diff --git a/src/geometry/mesh_geom_factory.hh b/src/geometry/mesh_geom_factory.hh index 74c464368..651e447f0 100644 --- a/src/geometry/mesh_geom_factory.hh +++ b/src/geometry/mesh_geom_factory.hh @@ -1,108 +1,108 @@ /** * @file mesh_geom_factory.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Feb 27 2015 * @date last modification: Thu Jan 14 2016 * * @brief Class for constructing the CGAL primitives of a mesh * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_GEOM_FACTORY_HH__ #define __AKANTU_MESH_GEOM_FACTORY_HH__ #include "aka_common.hh" #include "mesh.hh" #include "mesh_geom_abstract.hh" #include "tree_type_helper.hh" #include "geom_helper_functions.hh" #include <algorithm> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /** * @brief Class used to construct AABB tree for intersection computations * * This class constructs a CGAL AABB tree of one type of element in a mesh * for fast intersection computations. */ template<UInt dim, ElementType el_type, class Primitive, class Kernel> class MeshGeomFactory : public MeshGeomAbstract { public: /// Construct from mesh explicit MeshGeomFactory(Mesh & mesh); /// Desctructor virtual ~MeshGeomFactory(); public: /// Construct AABB tree for fast intersection computing virtual void constructData(GhostType ghost_type = _not_ghost); /** * @brief Construct a primitive and add it to a list of primitives * * This function needs to be specialized for every type that is wished to be supported. * @param node_coordinates coordinates of the nodes making up the element * @param id element number * @param list the primitive list (not used inside MeshGeomFactory) */ inline void addPrimitive( const Matrix<Real> & node_coordinates, UInt id, typename TreeTypeHelper<Primitive, Kernel>::container_type & list ); inline void addPrimitive( const Matrix<Real> & node_coordinates, UInt id ); /// Getter for the AABB tree const typename TreeTypeHelper<Primitive, Kernel>::tree & getTree() const { return *data_tree; } /// Getter for primitive list const typename TreeTypeHelper<Primitive, Kernel>::container_type & getPrimitiveList() const { return primitive_list; } protected: /// AABB data tree typename TreeTypeHelper<Primitive, Kernel>::tree * data_tree; /// Primitive list typename TreeTypeHelper<Primitive, Kernel>::container_type primitive_list; }; -__END_AKANTU__ +} // akantu #include "mesh_geom_factory_tmpl.hh" #endif // __AKANTU_MESH_GEOM_FACTORY_HH__ diff --git a/src/geometry/mesh_geom_factory_tmpl.hh b/src/geometry/mesh_geom_factory_tmpl.hh index 9f2450e3b..dfd7f01e3 100644 --- a/src/geometry/mesh_geom_factory_tmpl.hh +++ b/src/geometry/mesh_geom_factory_tmpl.hh @@ -1,259 +1,259 @@ /** * @file mesh_geom_factory_tmpl.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Clement Roux <clement.roux@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Feb 27 2015 * @date last modification: Thu Jan 14 2016 * * @brief Class for constructing the CGAL primitives of a mesh * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_MESH_GEOM_FACTORY_TMPL_HH__ #define __AKANTU_MESH_GEOM_FACTORY_TMPL_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh_geom_common.hh" #include "mesh_geom_factory.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { template<UInt dim, ElementType type, class Primitive, class Kernel> MeshGeomFactory<dim, type, Primitive, Kernel>::MeshGeomFactory(Mesh & mesh) : MeshGeomAbstract(mesh), data_tree(NULL), primitive_list() {} template<UInt dim, ElementType type, class Primitive, class Kernel> MeshGeomFactory<dim, type, Primitive, Kernel>::~MeshGeomFactory() { delete data_tree; } /** * This function loops over the elements of `type` in the mesh and creates the * AABB tree of geometrical primitves (`data_tree`). */ template<UInt dim, ElementType type, class Primitive, class Kernel> void MeshGeomFactory<dim, type, Primitive, Kernel>::constructData(GhostType ghost_type) { AKANTU_DEBUG_IN(); primitive_list.clear(); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); const Array<UInt> & connectivity = mesh.getConnectivity(type, ghost_type); const Array<Real> & nodes = mesh.getNodes(); UInt el_index = 0; Array<UInt>::const_vector_iterator it = connectivity.begin(nb_nodes_per_element); Array<UInt>::const_vector_iterator end = connectivity.end(nb_nodes_per_element); Matrix<Real> node_coordinates(dim, nb_nodes_per_element); // This loop builds the list of primitives for (; it != end ; ++it, ++el_index) { const Vector<UInt> & el_connectivity = *it; for (UInt i = 0 ; i < nb_nodes_per_element ; i++) for (UInt j = 0 ; j < dim ; j++) node_coordinates(j, i) = nodes(el_connectivity(i), j); // the unique elemental id assigned to the primitive is the // linearized element index over ghost type addPrimitive(node_coordinates, el_index); } delete data_tree; // This condition allows the use of the mesh geom module // even if types are not compatible with AABB tree algorithm if (TreeTypeHelper<Primitive, Kernel>::is_valid) data_tree = new typename TreeTypeHelper<Primitive, Kernel>::tree(primitive_list.begin(), primitive_list.end()); AKANTU_DEBUG_OUT(); } template<UInt dim, ElementType type, class Primitive, class Kernel> void MeshGeomFactory<dim, type, Primitive, Kernel>::addPrimitive(const Matrix<Real> & node_coordinates, UInt id) { this->addPrimitive(node_coordinates, id, this->primitive_list); } // (2D, _triangle_3) decomposed into Triangle<Cartesian> template<> inline void MeshGeomFactory<2, _triangle_3, Triangle<Cartesian>, Cartesian>::addPrimitive( const Matrix<Real> & node_coordinates, UInt id, TreeTypeHelper<Triangle<Cartesian>, Cartesian>::container_type & list) { TreeTypeHelper<Triangle<Cartesian>, Cartesian>::point_type a(node_coordinates(0, 0), node_coordinates(1, 0), 0.), b(node_coordinates(0, 1), node_coordinates(1, 1), 0.), c(node_coordinates(0, 2), node_coordinates(1, 2), 0.); Triangle<Cartesian> t(a, b, c); t.setId(id); list.push_back(t); } // (2D, _triangle_6) decomposed into Triangle<Cartesian> template<> inline void MeshGeomFactory<2, _triangle_6, Triangle<Cartesian>, Cartesian>::addPrimitive( const Matrix<Real> & node_coordinates, UInt id, TreeTypeHelper<Triangle<Cartesian>, Cartesian>::container_type & list) { TreeTypeHelper<Triangle<Cartesian>, Cartesian>::point_type a(node_coordinates(0, 0), node_coordinates(1, 0), 0.), b(node_coordinates(0, 1), node_coordinates(1, 1), 0.), c(node_coordinates(0, 2), node_coordinates(1, 2), 0.); Triangle<Cartesian> t(a, b, c); t.setId(id); list.push_back(t); } // (2D, _triangle_3) decomposed into Line_arc<Spherical> template<> inline void MeshGeomFactory<2, _triangle_3, Line_arc<Spherical>, Spherical>::addPrimitive( const Matrix<Real> & node_coordinates, UInt id, TreeTypeHelper<Line_arc<Spherical>, Spherical>::container_type & list) { TreeTypeHelper<Line_arc<Spherical>, Spherical>::point_type a(node_coordinates(0, 0), node_coordinates(1, 0), 0.), b(node_coordinates(0, 1), node_coordinates(1, 1), 0.), c(node_coordinates(0, 2), node_coordinates(1, 2), 0.); /*std::cout << "elem " << id << " node 1 : x_node=" << node_coordinates(0, 0) << ", x_arc_node=" << a.x() << ", y_node=" << node_coordinates(1, 0) << ", y_arc_node=" << a.y() << std::endl ; std::cout << "elem " << id << " node 2 : x_node=" << node_coordinates(0, 1) << ", x_arc_node=" << b.x() << ", y_node=" << node_coordinates(1, 1) << ", y_arc_node=" << b.y() << std::endl ; std::cout << "elem " << id << " node 2 : x_node=" << node_coordinates(0, 2) << ", x_arc_node=" << c.x() << ", y_node=" << node_coordinates(1, 2) << ", y_arc_node=" << c.y() << std::endl ;*/ CGAL::Line_3<Spherical> l1(a, b), l2(b, c), l3(c, a); Line_arc<Spherical> s1(l1,a, b), s2(l2, b, c), s3(l3, c, a); s1.setId(id); s1.setSegId(0); s2.setId(id); s2.setSegId(1); s3.setId(id); s3.setSegId(2); list.push_back(s1); list.push_back(s2); list.push_back(s3); } #if defined(AKANTU_IGFEM) // (2D, _igfem_triangle_4) decomposed into Line_arc<Spherical> template<> inline void MeshGeomFactory<2, _igfem_triangle_4, Line_arc<Spherical>, Spherical>::addPrimitive( const Matrix<Real> & node_coordinates, UInt id, TreeTypeHelper<Line_arc<Spherical>, Spherical>::container_type & list) { TreeTypeHelper<Line_arc<Spherical>, Spherical>::point_type a(node_coordinates(0, 0), node_coordinates(1, 0), 0.), b(node_coordinates(0, 1), node_coordinates(1, 1), 0.), c(node_coordinates(0, 2), node_coordinates(1, 2), 0.); CGAL::Line_3<Spherical> l1(a, b), l2(b, c), l3(c, a); Line_arc<Spherical> s1(l1,a, b), s2(l2, b, c), s3(l3, c, a); s1.setId(id); s1.setSegId(0); s2.setId(id); s2.setSegId(1); s3.setId(id); s3.setSegId(2); list.push_back(s1); list.push_back(s2); list.push_back(s3); } // (2D, _igfem_triangle_4) decomposed into Line_arc<Spherical> template<> inline void MeshGeomFactory<2, _igfem_triangle_5, Line_arc<Spherical>, Spherical>::addPrimitive( const Matrix<Real> & node_coordinates, UInt id, TreeTypeHelper<Line_arc<Spherical>, Spherical>::container_type & list) { TreeTypeHelper<Line_arc<Spherical>, Spherical>::point_type a(node_coordinates(0, 0), node_coordinates(1, 0), 0.), b(node_coordinates(0, 1), node_coordinates(1, 1), 0.), c(node_coordinates(0, 2), node_coordinates(1, 2), 0.); CGAL::Line_3<Spherical> l1(a, b), l2(b, c), l3(c, a); Line_arc<Spherical> s1(l1,a, b), s2(l2, b, c), s3(l3, c, a); s1.setId(id); s1.setSegId(0); s2.setId(id); s2.setSegId(1); s3.setId(id); s3.setSegId(2); list.push_back(s1); list.push_back(s2); list.push_back(s3); } #endif // (3D, _tetrahedron_4) decomposed into Triangle<Cartesian> template<> inline void MeshGeomFactory<3, _tetrahedron_4, Triangle<Cartesian>, Cartesian>::addPrimitive( const Matrix<Real> & node_coordinates, UInt id, TreeTypeHelper<Triangle<Cartesian>, Cartesian>::container_type & list) { TreeTypeHelper<Triangle<Cartesian>, Cartesian>::point_type a(node_coordinates(0, 0), node_coordinates(1, 0), node_coordinates(2, 0)), b(node_coordinates(0, 1), node_coordinates(1, 1), node_coordinates(2, 1)), c(node_coordinates(0, 2), node_coordinates(1, 2), node_coordinates(2, 2)), d(node_coordinates(0, 3), node_coordinates(1, 3), node_coordinates(2, 3)); Triangle<Cartesian> t1(a, b, c), t2(b, c, d), t3(c, d, a), t4(d, a, b); t1.setId(id); t2.setId(id); t3.setId(id); t4.setId(id); list.push_back(t1); list.push_back(t2); list.push_back(t3); list.push_back(t4); } -__END_AKANTU__ +} // akantu #endif // __AKANTU_MESH_GEOM_FACTORY_TMPL_HH__ diff --git a/src/geometry/mesh_geom_intersector.hh b/src/geometry/mesh_geom_intersector.hh index 230d77249..ae1d3a633 100644 --- a/src/geometry/mesh_geom_intersector.hh +++ b/src/geometry/mesh_geom_intersector.hh @@ -1,72 +1,72 @@ /** * @file mesh_geom_intersector.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Clement Roux <clement.roux@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Apr 29 2015 * @date last modification: Thu Jan 14 2016 * * @brief General class for intersection computations * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_GEOM_INTERSECTOR_HH__ #define __AKANTU_MESH_GEOM_INTERSECTOR_HH__ #include "aka_common.hh" #include "mesh_abstract_intersector.hh" #include "mesh_geom_factory.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /** * @brief Class used to perform intersections on a mesh and construct output data */ template<UInt dim, ElementType type, class Primitive, class Query, class Kernel> class MeshGeomIntersector : public MeshAbstractIntersector<Query> { public: /// Construct from mesh explicit MeshGeomIntersector(Mesh & mesh); /// Destructor virtual ~MeshGeomIntersector(); public: /// Construct the primitive tree object virtual void constructData(GhostType ghost_type = _not_ghost); protected: /// Factory object containing the primitive tree MeshGeomFactory<dim, type, Primitive, Kernel> factory; }; -__END_AKANTU__ +} // akantu #include "mesh_geom_intersector_tmpl.hh" #endif // __AKANTU_MESH_GEOM_INTERSECTOR_HH__ diff --git a/src/geometry/mesh_geom_intersector_tmpl.hh b/src/geometry/mesh_geom_intersector_tmpl.hh index ec2454717..a1a5582b2 100644 --- a/src/geometry/mesh_geom_intersector_tmpl.hh +++ b/src/geometry/mesh_geom_intersector_tmpl.hh @@ -1,62 +1,62 @@ /** * @file mesh_geom_intersector_tmpl.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Wed Apr 29 2015 * @date last modification: Thu Jan 14 2016 * * @brief General class for intersection computations * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_GEOM_INTERSECTOR_TMPL_HH__ #define __AKANTU_MESH_GEOM_INTERSECTOR_TMPL_HH__ #include "aka_common.hh" #include "mesh_geom_intersector.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { template<UInt dim, ElementType type, class Primitive, class Query, class Kernel> MeshGeomIntersector<dim, type, Primitive, Query, Kernel>::MeshGeomIntersector(Mesh & mesh) : MeshAbstractIntersector<Query>(mesh), factory(mesh) {} template<UInt dim, ElementType type, class Primitive, class Query, class Kernel> MeshGeomIntersector<dim, type, Primitive, Query, Kernel>::~MeshGeomIntersector() {} template<UInt dim, ElementType type, class Primitive, class Query, class Kernel> void MeshGeomIntersector<dim, type, Primitive, Query, Kernel>::constructData(GhostType ghost_type) { this->intersection_points->resize(0); factory.constructData(ghost_type); } -__END_AKANTU__ +} // akantu #endif // __AKANTU_MESH_GEOM_INTERSECTOR_TMPL_HH__ diff --git a/src/geometry/mesh_segment_intersector.hh b/src/geometry/mesh_segment_intersector.hh index 940a8105a..8ef17445d 100644 --- a/src/geometry/mesh_segment_intersector.hh +++ b/src/geometry/mesh_segment_intersector.hh @@ -1,103 +1,103 @@ /** * @file mesh_segment_intersector.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Clement Roux <clement.roux@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Apr 29 2015 * @date last modification: Thu Jan 14 2016 * * @brief Computation of mesh intersection with segments * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_SEGMENT_INTERSECTOR_HH__ #define __AKANTU_MESH_SEGMENT_INTERSECTOR_HH__ #include "aka_common.hh" #include "mesh_geom_intersector.hh" #include "mesh_geom_common.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /// Here, we know what kernel we have to use typedef Cartesian K; template<UInt dim, ElementType type> class MeshSegmentIntersector : public MeshGeomIntersector<dim, type, Triangle<K>, K::Segment_3, K> { /// Parent class type typedef MeshGeomIntersector<dim, type, Triangle<K>, K::Segment_3, K> parent_type; /// Result of intersection function type typedef typename IntersectionTypeHelper<TreeTypeHelper< Triangle<K>, K>, K::Segment_3>::intersection_type result_type; /// Pair of segments and element id typedef std::pair<K::Segment_3, UInt> pair_type; public: /// Construct from mesh explicit MeshSegmentIntersector(Mesh & mesh, Mesh & result_mesh); /// Destructor virtual ~MeshSegmentIntersector(); public: /** * @brief Computes the intersection of the mesh with a segment * * @param query the segment to compute the intersections with the mesh */ virtual void computeIntersectionQuery(const K::Segment_3 & query); /// Compute intersection points between the mesh and a query virtual void computeMeshQueryIntersectionPoint(const K::Segment_3 & query, UInt nb_old_nodes); /// Compute the embedded mesh virtual void buildResultFromQueryList(const std::list<K::Segment_3> & query_list); void setPhysicalName(const std::string & other) { current_physical_name = other; } protected: /// Compute segments from intersection list void computeSegments(const std::list<result_type> & intersections, std::set<pair_type, segmentPairsLess> & segments, const K::Segment_3 & query); protected: /// Result mesh Mesh & result_mesh; /// Physical name of the current batch of queries std::string current_physical_name; }; -__END_AKANTU__ +} // akantu #include "mesh_segment_intersector_tmpl.hh" #endif // __AKANTU_MESH_SEGMENT_INTERSECTOR_HH__ diff --git a/src/geometry/mesh_segment_intersector_tmpl.hh b/src/geometry/mesh_segment_intersector_tmpl.hh index 37fe10631..897bfcfb8 100644 --- a/src/geometry/mesh_segment_intersector_tmpl.hh +++ b/src/geometry/mesh_segment_intersector_tmpl.hh @@ -1,270 +1,270 @@ /** * @file mesh_segment_intersector_tmpl.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Clement Roux <clement.roux@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Apr 29 2015 * @date last modification: Thu Jan 14 2016 * * @brief Computation of mesh intersection with segments * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_SEGMENT_INTERSECTOR_TMPL_HH__ #define __AKANTU_MESH_SEGMENT_INTERSECTOR_TMPL_HH__ #include "aka_common.hh" #include "mesh_geom_common.hh" #include "tree_type_helper.hh" -__BEGIN_AKANTU__ +namespace akantu { template<UInt dim, ElementType type> MeshSegmentIntersector<dim, type>::MeshSegmentIntersector(Mesh & mesh, Mesh & result_mesh): parent_type(mesh), result_mesh(result_mesh), current_physical_name() { this->intersection_points = new Array<Real>(0,dim); this->constructData(); } template<UInt dim, ElementType type> MeshSegmentIntersector<dim, type>::~MeshSegmentIntersector() {} template<UInt dim, ElementType type> void MeshSegmentIntersector<dim, type>::computeIntersectionQuery(const K::Segment_3 & query) { AKANTU_DEBUG_IN(); result_mesh.addConnectivityType(_segment_2, _not_ghost); result_mesh.addConnectivityType(_segment_2, _ghost); std::list<result_type> result_list; std::set<std::pair<K::Segment_3, UInt>, segmentPairsLess> segment_set; this->factory.getTree().all_intersections(query, std::back_inserter(result_list)); this->computeSegments(result_list, segment_set, query); // Arrays for storing nodes and connectivity Array<Real> & nodes = result_mesh.getNodes(); Array<UInt> & connectivity = result_mesh.getConnectivity(_segment_2); // Arrays for storing associated element and physical name bool valid_elemental_data = true; Array<Element> * associated_element = NULL; Array<std::string> * associated_physical_name = NULL; try { associated_element = &result_mesh.getData<Element>("associated_element", _segment_2); associated_physical_name = &result_mesh.getData<std::string>("physical_names", _segment_2); } catch (debug::Exception & e) { valid_elemental_data = false; } std::set<pair_type, segmentPairsLess>::iterator it = segment_set.begin(), end = segment_set.end(); // Loop over the segment pairs for (; it != end ; ++it) { if (!it->first.is_degenerate()) { Vector<UInt> segment_connectivity(2); segment_connectivity(0) = result_mesh.getNbNodes(); segment_connectivity(1) = result_mesh.getNbNodes() + 1; connectivity.push_back(segment_connectivity); // Copy nodes Vector<Real> source(dim), target(dim); for (UInt j = 0 ; j < dim ; j++) { source(j) = it->first.source()[j]; target(j) = it->first.target()[j]; } nodes.push_back(source); nodes.push_back(target); // Copy associated element info if (valid_elemental_data) { associated_element->push_back(Element(type, it->second)); associated_physical_name->push_back(current_physical_name); } } } AKANTU_DEBUG_OUT(); } template<UInt dim, ElementType type> void MeshSegmentIntersector<dim, type>:: computeMeshQueryIntersectionPoint(const K::Segment_3 & query, UInt nb_old_nodes) { AKANTU_DEBUG_ERROR("The method: computeMeshQueryIntersectionPoint has not been implemented in class MeshSegmentIntersector!"); } template<UInt dim, ElementType type> void MeshSegmentIntersector<dim, type>::buildResultFromQueryList(const std::list<K::Segment_3> & query_list) { AKANTU_DEBUG_IN(); this->computeIntersectionQueryList(query_list); AKANTU_DEBUG_OUT(); } template<UInt dim, ElementType type> void MeshSegmentIntersector<dim, type>::computeSegments(const std::list<result_type> & intersections, std::set<pair_type, segmentPairsLess> & segments, const K::Segment_3 & query) { AKANTU_DEBUG_IN(); /* * Number of intersections = 0 means * * - query is completely outside mesh * - query is completely inside primitive * * We try to determine the case and still construct the segment list */ if (intersections.size() == 0) { // We look at all the primitives intersected by two rays // If there is one primitive in common, then query is inside // that primitive K::Ray_3 ray1(query.source(), query.target()); K::Ray_3 ray2(query.target(), query.source()); std::set<UInt> ray1_results, ray2_results; this->factory.getTree().all_intersected_primitives(ray1, std::inserter(ray1_results, ray1_results.begin())); this->factory.getTree().all_intersected_primitives(ray2, std::inserter(ray2_results, ray2_results.begin())); bool inside_primitive = false; UInt primitive_id = 0; std::set<UInt>::iterator ray2_it = ray2_results.begin(), ray2_end = ray2_results.end(); // Test if first list contains an element of second list for (; ray2_it != ray2_end && !inside_primitive ; ++ray2_it) { if (ray1_results.find(*ray2_it) != ray1_results.end()) { inside_primitive = true; primitive_id = *ray2_it; } } if (inside_primitive) { segments.insert(std::make_pair(query, primitive_id)); } } else { typename std::list<result_type>::const_iterator it = intersections.begin(), end = intersections.end(); for(; it != end ; ++it) { UInt el = (*it)->second; // Result of intersection is a segment if (const K::Segment_3 * segment = boost::get<K::Segment_3>(&((*it)->first))) { // Check if the segment was alread created segments.insert(std::make_pair(*segment, el)); } // Result of intersection is a point else if (const K::Point_3 * point = boost::get<K::Point_3>(&((*it)->first))) { // We only want to treat points differently if we're in 3D with Tetra4 elements // This should be optimized by compilator if (dim == 3 && type == _tetrahedron_4) { UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); TreeTypeHelper<Triangle<K>, K>::container_type facets; const Array<Real> & nodes = this->mesh.getNodes(); Array<UInt>::const_vector_iterator connectivity_vec = this->mesh.getConnectivity(type).begin(nb_nodes_per_element); const Vector<UInt> & el_connectivity = connectivity_vec[el]; Matrix<Real> node_coordinates(dim, nb_nodes_per_element); for (UInt i = 0 ; i < nb_nodes_per_element ; i++) for (UInt j = 0 ; j < dim ; j++) node_coordinates(j, i) = nodes(el_connectivity(i), j); this->factory.addPrimitive(node_coordinates, el, facets); // Local tree TreeTypeHelper<Triangle<K>, K>::tree * local_tree = new TreeTypeHelper<Triangle<K>, K>::tree(facets.begin(), facets.end()); // Compute local intersections (with current element) std::list<result_type> local_intersections; local_tree->all_intersections(query, std::back_inserter(local_intersections)); bool out_point_found = false; typename std::list<result_type>::const_iterator local_it = local_intersections.begin(), local_end = local_intersections.end(); for (; local_it != local_end ; ++local_it) { if (const K::Point_3 * local_point = boost::get<K::Point_3>(&((*local_it)->first))) { if (!comparePoints(*point, *local_point)) { K::Segment_3 seg(*point, *local_point); segments.insert(std::make_pair(seg, el)); out_point_found = true; } } } if (!out_point_found) { TreeTypeHelper<Triangle<K>, K>::point_type a(node_coordinates(0, 0), node_coordinates(1, 0), node_coordinates(2, 0)), b(node_coordinates(0, 1), node_coordinates(1, 1), node_coordinates(2, 1)), c(node_coordinates(0, 2), node_coordinates(1, 2), node_coordinates(2, 2)), d(node_coordinates(0, 3), node_coordinates(1, 3), node_coordinates(2, 3)); K::Tetrahedron_3 tetra(a, b, c, d); const K::Point_3 * inside_point = NULL; if (tetra.has_on_bounded_side(query.source()) && !tetra.has_on_boundary(query.source())) inside_point = &query.source(); else if (tetra.has_on_bounded_side(query.target()) && !tetra.has_on_boundary(query.target())) inside_point = &query.target(); if (inside_point) { K::Segment_3 seg(*inside_point, *point); segments.insert(std::make_pair(seg, el)); } } delete local_tree; } } } } AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu #endif // __AKANTU_MESH_SEGMENT_INTERSECTOR_TMPL_HH__ diff --git a/src/geometry/mesh_sphere_intersector.hh b/src/geometry/mesh_sphere_intersector.hh index cc0b5335d..63bcea07b 100644 --- a/src/geometry/mesh_sphere_intersector.hh +++ b/src/geometry/mesh_sphere_intersector.hh @@ -1,105 +1,105 @@ /** * @file mesh_sphere_intersector.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Clement Roux <clement.roux@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue Jun 23 2015 * @date last modification: Thu Jan 14 2016 * * @brief Computation of mesh intersection with sphere(s) * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_SPHERE_INTERSECTOR_HH__ #define __AKANTU_MESH_SPHERE_INTERSECTOR_HH__ #include "aka_common.hh" #include "mesh_geom_intersector.hh" #include "mesh_geom_common.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /// Here, we know what kernel we have to use typedef Spherical SK; template<UInt dim, ElementType type> class MeshSphereIntersector : public MeshGeomIntersector<dim, type, Line_arc<SK>, SK::Sphere_3, SK> { /// Parent class type typedef MeshGeomIntersector<dim, type, Line_arc<SK>, SK::Sphere_3, SK> parent_type; /// Result of intersection function type typedef typename IntersectionTypeHelper<TreeTypeHelper< Triangle<K>, K>, K::Segment_3>::intersection_type result_type; /// Pair of intersection points and element id typedef std::pair<SK::Circular_arc_point_3, UInt> pair_type; public: /// Construct from mesh explicit MeshSphereIntersector(Mesh & mesh); /// Destructor virtual ~MeshSphereIntersector(); public: /// Construct the primitive tree object virtual void constructData(GhostType ghost_type = _not_ghost); /** * @brief Computes the intersection of the mesh with a sphere * * @param query (sphere) to compute the intersections with the mesh */ virtual void computeIntersectionQuery(const SK::Sphere_3 & query){ AKANTU_DEBUG_ERROR("This function is not implemented for spheres (It was to generic and has been replaced by computeMeshQueryIntersectionPoint"); } /// Compute intersection points between the mesh primitives (segments) and a query (surface in 3D or a curve in 2D), double intersection points for the same primitives are not considered. A maximum is set to the number of intersection nodes per element: 2 in 2D and 4 in 3D virtual void computeMeshQueryIntersectionPoint(const SK::Sphere_3 & query, UInt nb_old_nodes); /// Build the IGFEM mesh virtual void buildResultFromQueryList(const std::list<SK::Sphere_3> & query){ AKANTU_DEBUG_ERROR("This function is no longer implemented to split geometrical operations and dedicated result construction"); } /// Set the tolerance void setToleranceIntersectionOnNode(UInt tol) { this->tol_intersection_on_node = tol; } protected: /// tolerance for which the intersection is considered on the mesh node (relative to the segment lenght) Real tol_intersection_on_node; }; -__END_AKANTU__ +} // akantu #include "mesh_sphere_intersector_tmpl.hh" #endif // __AKANTU_MESH_SPHERE_INTERSECTOR_HH__ diff --git a/src/geometry/mesh_sphere_intersector_tmpl.hh b/src/geometry/mesh_sphere_intersector_tmpl.hh index 44a5120e0..07b2745fe 100644 --- a/src/geometry/mesh_sphere_intersector_tmpl.hh +++ b/src/geometry/mesh_sphere_intersector_tmpl.hh @@ -1,196 +1,196 @@ /** * @file mesh_sphere_intersector_tmpl.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Clement Roux <clement.roux@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue Jun 23 2015 * @date last modification: Thu Jan 14 2016 * * @brief Computation of mesh intersection with spheres * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_SPHERE_INTERSECTOR_TMPL_HH__ #define __AKANTU_MESH_SPHERE_INTERSECTOR_TMPL_HH__ #include "aka_common.hh" #include "mesh_geom_common.hh" #include "tree_type_helper.hh" #include "mesh_sphere_intersector.hh" #include "static_communicator.hh" -__BEGIN_AKANTU__ +namespace akantu { template<UInt dim, ElementType type> MeshSphereIntersector<dim, type>::MeshSphereIntersector(Mesh & mesh): parent_type(mesh), tol_intersection_on_node(1e-10) { #if defined(AKANTU_IGFEM) if( (type == _triangle_3) || (type == _igfem_triangle_4) || (type == _igfem_triangle_5) ){ const_cast<UInt &>(this->nb_seg_by_el) = 3; } else { AKANTU_DEBUG_ERROR("Not ready for mesh type " << type); } #else if( (type != _triangle_3) ) AKANTU_DEBUG_ERROR("Not ready for mesh type " << type); #endif // initialize the intersection pointsss array with the spatial dimension this->intersection_points = new Array<Real>(0,dim); // A maximum is set to the number of intersection nodes per element to limit the size of new_node_per_elem: 2 in 2D and 4 in 3D this->new_node_per_elem = new Array<UInt>(0, 1 + 4 * (dim-1)); } template<UInt dim, ElementType type> MeshSphereIntersector<dim, type>::~MeshSphereIntersector() { delete this->new_node_per_elem; delete this->intersection_points; } template<UInt dim, ElementType type> void MeshSphereIntersector<dim, type>::constructData(GhostType ghost_type) { this->new_node_per_elem->resize(this->mesh.getNbElement(type, ghost_type)); this->new_node_per_elem->clear(); MeshGeomIntersector<dim, type, Line_arc<SK>, SK::Sphere_3, SK>::constructData(ghost_type); } template<UInt dim, ElementType type> void MeshSphereIntersector<dim, type>:: computeMeshQueryIntersectionPoint(const SK::Sphere_3 & query, UInt nb_old_nodes) { /// function to replace computeIntersectionQuery in a more generic geometry module version // The newNodeEvent is not send from this method who only compute the intersection points AKANTU_DEBUG_IN(); Array<Real> & nodes = this->mesh.getNodes(); UInt nb_node = nodes.getSize() + this->intersection_points->getSize(); // Tolerance for proximity checks should be defined by user Real global_tolerance = Math::getTolerance(); Math::setTolerance(tol_intersection_on_node); typedef boost::variant<pair_type> sk_inter_res; TreeTypeHelper<Line_arc<Spherical>, Spherical>::const_iterator it = this->factory.getPrimitiveList().begin(), end= this->factory.getPrimitiveList().end(); for (; it != end ; ++it) { // loop on the primitives (segments) std::list<sk_inter_res> s_results; CGAL::intersection(*it, query, std::back_inserter(s_results)); if (s_results.size() == 1) { // just one point if (pair_type * pair = boost::get<pair_type>(&s_results.front())) { if (pair->second == 1) { // not a point tangent to the sphere // the intersection point written as a vector Vector<Real> new_node(dim, 0.0); Cartesian::Point_3 point(CGAL::to_double(pair->first.x()), CGAL::to_double(pair->first.y()), CGAL::to_double(pair->first.z())); for (UInt i = 0 ; i < dim ; i++) { new_node(i) = point[i]; } /// boolean to decide wheter intersection point is on a standard node of the mesh or not bool is_on_mesh = false; /// boolean to decide if this intersection point has been already computed for a neighbor element bool is_new = true; /// check if intersection point has already been computed UInt n = nb_old_nodes; // check if we already compute this intersection and add it as a node for a neighboor element of another type Array<Real>::vector_iterator existing_node = nodes.begin(dim); for (; n < nodes.getSize() ; ++n) {// loop on the nodes from nb_old_nodes if (Math::are_vector_equal(dim, new_node.storage(), existing_node[n].storage())) { is_new = false; break; } } if(is_new){ Array<Real>::vector_iterator intersection_points_it = this->intersection_points->begin(dim); Array<Real>::vector_iterator intersection_points_end = this->intersection_points->end(dim); for (; intersection_points_it != intersection_points_end ; ++intersection_points_it, ++n) { if (Math::are_vector_equal(dim, new_node.storage(), intersection_points_it->storage())) { is_new = false; break; } } } // get the initial and final points of the primitive (segment) and write them as vectors Cartesian::Point_3 source_cgal(CGAL::to_double(it->source().x()), CGAL::to_double(it->source().y()), CGAL::to_double(it->source().z())); Cartesian::Point_3 target_cgal(CGAL::to_double(it->target().x()), CGAL::to_double(it->target().y()), CGAL::to_double(it->target().z())); Vector<Real> source(dim), target(dim); for (UInt i = 0 ; i < dim ; i++) { source(i) = source_cgal[i]; target(i) = target_cgal[i]; } // Check if we are close from a node of the primitive (segment) if (Math::are_vector_equal(dim, source.storage(), new_node.storage()) || Math::are_vector_equal(dim, target.storage(), new_node.storage())) { is_on_mesh = true; is_new = false; } if (is_new) {// if the intersection point is a new one add it to the list this->intersection_points->push_back(new_node); nb_node++; } // deduce the element id UInt element_id = it->id(); // fill the new_node_per_elem array if (!is_on_mesh) { // if the node is not on a mesh node UInt & nb_new_nodes_per_el = (*this->new_node_per_elem)(element_id, 0); nb_new_nodes_per_el += 1; AKANTU_DEBUG_ASSERT(2 * nb_new_nodes_per_el < this->new_node_per_elem->getNbComponent(), "You might have to interface crossing the same material"); (*this->new_node_per_elem)(element_id, (2 * nb_new_nodes_per_el) - 1) = n; (*this->new_node_per_elem)(element_id, 2 * nb_new_nodes_per_el) = it->segId(); } } } } } Math::setTolerance(global_tolerance); AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu #endif // __AKANTU_MESH_SPHERE_INTERSECTOR_TMPL_HH__ diff --git a/src/geometry/tree_type_helper.hh b/src/geometry/tree_type_helper.hh index 3e6646664..853bc63ff 100644 --- a/src/geometry/tree_type_helper.hh +++ b/src/geometry/tree_type_helper.hh @@ -1,111 +1,111 @@ /** * @file tree_type_helper.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Fri Jan 04 2013 * @date last modification: Thu Jan 14 2016 * * @brief Converts element types of a mesh to CGAL primitive types * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_TREE_TYPE_HELPER_HH__ #define __AKANTU_TREE_TYPE_HELPER_HH__ #include "aka_common.hh" #include "line_arc.hh" #include "triangle.hh" #include "tetrahedron.hh" #include "aabb_primitive.hh" #include "mesh_geom_common.hh" #include <CGAL/AABB_traits.h> #include <CGAL/AABB_tree.h> -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /// Replacement class for algorithm that can't use the AABB tree types template<typename iterator> struct VoidTree { VoidTree(const iterator & begin, const iterator & end) {} }; /// Helper class used to ease the use of CGAL AABB tree algorithm template<class Primitive, class Kernel> struct TreeTypeHelper { static const bool is_valid = false; typedef Primitive primitive_type; typedef typename std::list<primitive_type> container_type; typedef typename container_type::iterator iterator; typedef typename container_type::const_iterator const_iterator; typedef typename CGAL::Point_3<Kernel> point_type; typedef VoidTree<iterator> tree; }; /// Helper class used to ease the use of intersections template<class TTHelper, class Query> struct IntersectionTypeHelper; /** * Macro used to specialize TreeTypeHelper * @param my_primitive associated primitive type * @param my_query query_type * @param my_kernel kernel type */ #define TREE_TYPE_HELPER_MACRO(my_primitive, my_query, my_kernel) \ template<> \ struct TreeTypeHelper<my_primitive<my_kernel>, my_kernel> { \ static const bool is_valid = true; \ typedef my_primitive<my_kernel> primitive_type; \ typedef my_primitive##_primitive aabb_primitive_type; \ typedef CGAL::Point_3<my_kernel> point_type; \ \ typedef std::list<primitive_type> container_type; \ typedef container_type::iterator iterator; \ typedef CGAL::AABB_traits<my_kernel, aabb_primitive_type> aabb_traits_type; \ typedef CGAL::AABB_tree<aabb_traits_type> tree; \ typedef tree::Primitive_id id_type; \ }; \ \ template<> \ struct IntersectionTypeHelper<TreeTypeHelper<my_primitive<my_kernel>, my_kernel>, my_query> { \ typedef boost::optional< \ TreeTypeHelper<my_primitive<my_kernel>, my_kernel>::tree::Intersection_and_primitive_id<my_query>::Type \ > intersection_type; \ } TREE_TYPE_HELPER_MACRO(Triangle, Cartesian::Segment_3, Cartesian); //TREE_TYPE_HELPER_MACRO(Line_arc, Spherical::Sphere_3, Spherical); #undef TREE_TYPE_HELPER_MACRO -__END_AKANTU__ +} // akantu #endif // __AKANTU_TREE_TYPE_HELPER_HH__ diff --git a/src/io/dumper/dumpable.cc b/src/io/dumper/dumpable.cc index fceb2baee..c7a27ef22 100644 --- a/src/io/dumper/dumpable.cc +++ b/src/io/dumper/dumpable.cc @@ -1,285 +1,285 @@ /** * @file dumpable.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Thu Jan 21 2016 * * @brief Implementation of the dumpable interface * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "dumpable.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER #include <io_helper.hh> -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ Dumpable::Dumpable() : default_dumper("") {} /* -------------------------------------------------------------------------- */ Dumpable::~Dumpable() { DumperMap::iterator it = dumpers.begin(); DumperMap::iterator end = dumpers.end(); for (; it != end; ++it) { delete it->second; } } /* -------------------------------------------------------------------------- */ void Dumpable::registerExternalDumper(DumperIOHelper & dumper, const std::string & dumper_name, const bool is_default) { this->dumpers[dumper_name] = &dumper; if (is_default) this->default_dumper = dumper_name; } /* -------------------------------------------------------------------------- */ void Dumpable::addDumpMesh(const Mesh & mesh, UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & element_kind) { this->addDumpMeshToDumper(this->default_dumper, mesh, spatial_dimension, ghost_type, element_kind); } /* -------------------------------------------------------------------------- */ void Dumpable::addDumpMeshToDumper(const std::string & dumper_name, const Mesh & mesh, UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & element_kind) { DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.registerMesh(mesh, spatial_dimension, ghost_type, element_kind); } /* -------------------------------------------------------------------------- */ void Dumpable::addDumpFilteredMesh( const Mesh & mesh, const ElementTypeMapArray<UInt> & elements_filter, const Array<UInt> & nodes_filter, UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & element_kind) { this->addDumpFilteredMeshToDumper(this->default_dumper, mesh, elements_filter, nodes_filter, spatial_dimension, ghost_type, element_kind); } /* -------------------------------------------------------------------------- */ void Dumpable::addDumpFilteredMeshToDumper( const std::string & dumper_name, const Mesh & mesh, const ElementTypeMapArray<UInt> & elements_filter, const Array<UInt> & nodes_filter, UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & element_kind) { DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.registerFilteredMesh(mesh, elements_filter, nodes_filter, spatial_dimension, ghost_type, element_kind); } /* -------------------------------------------------------------------------- */ void Dumpable::addDumpField(const std::string & field_id) { this->addDumpFieldToDumper(this->default_dumper, field_id); } /* -------------------------------------------------------------------------- */ void Dumpable::addDumpFieldToDumper(__attribute__((unused)) const std::string & dumper_name, __attribute__((unused)) const std::string & field_id) { AKANTU_DEBUG_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ void Dumpable::addDumpFieldExternal(const std::string & field_id, dumper::Field * field) { this->addDumpFieldExternalToDumper(this->default_dumper, field_id, field); } /* -------------------------------------------------------------------------- */ void Dumpable::addDumpFieldExternalToDumper(const std::string & dumper_name, const std::string & field_id, dumper::Field * field) { DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.registerField(field_id, field); } /* -------------------------------------------------------------------------- */ void Dumpable::removeDumpField(const std::string & field_id) { this->removeDumpFieldFromDumper(this->default_dumper, field_id); } /* -------------------------------------------------------------------------- */ void Dumpable::removeDumpFieldFromDumper(const std::string & dumper_name, const std::string & field_id) { DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.unRegisterField(field_id); } /* -------------------------------------------------------------------------- */ void Dumpable::addDumpFieldVector(const std::string & field_id) { this->addDumpFieldVectorToDumper(this->default_dumper, field_id); } /* -------------------------------------------------------------------------- */ void Dumpable::addDumpFieldVectorToDumper(__attribute__((unused)) const std::string & dumper_name, __attribute__((unused)) const std::string & field_id) { AKANTU_DEBUG_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ void Dumpable::addDumpFieldTensor(const std::string & field_id) { this->addDumpFieldTensorToDumper(this->default_dumper, field_id); } /* -------------------------------------------------------------------------- */ void Dumpable::addDumpFieldTensorToDumper(__attribute__((unused)) const std::string & dumper_name, __attribute__((unused)) const std::string & field_id) { AKANTU_DEBUG_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ void Dumpable::setDirectory(const std::string & directory) { this->setDirectoryToDumper(this->default_dumper, directory); } /* -------------------------------------------------------------------------- */ void Dumpable::setDirectoryToDumper(const std::string & dumper_name, const std::string & directory) { DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.setDirectory(directory); } /* -------------------------------------------------------------------------- */ void Dumpable::setBaseName(const std::string & basename) { this->setBaseNameToDumper(this->default_dumper, basename); } /* -------------------------------------------------------------------------- */ void Dumpable::setBaseNameToDumper(const std::string & dumper_name, const std::string & basename) { DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.setBaseName(basename); } /* -------------------------------------------------------------------------- */ void Dumpable::setTimeStepToDumper(Real time_step) { this->setTimeStepToDumper(this->default_dumper, time_step); } /* -------------------------------------------------------------------------- */ void Dumpable::setTimeStepToDumper(const std::string & dumper_name, Real time_step) { DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.setTimeStep(time_step); } /* -------------------------------------------------------------------------- */ void Dumpable::setTextModeToDumper(const std::string & dumper_name) { DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.getDumper().setMode(iohelper::TEXT); } /* -------------------------------------------------------------------------- */ void Dumpable::setTextModeToDumper() { DumperIOHelper & dumper = this->getDumper(this->default_dumper); dumper.getDumper().setMode(iohelper::TEXT); } /* -------------------------------------------------------------------------- */ void Dumpable::dump(const std::string & dumper_name) { DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.dump(); } /* -------------------------------------------------------------------------- */ void Dumpable::dump() { this->dump(this->default_dumper); } /* -------------------------------------------------------------------------- */ void Dumpable::dump(const std::string & dumper_name, UInt step) { DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.dump(step); } /* -------------------------------------------------------------------------- */ void Dumpable::dump(UInt step) { this->dump(this->default_dumper, step); } /* -------------------------------------------------------------------------- */ void Dumpable::dump(const std::string & dumper_name, Real time, UInt step) { DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.dump(time, step); } /* -------------------------------------------------------------------------- */ void Dumpable::dump(Real time, UInt step) { this->dump(this->default_dumper, time, step); } /* -------------------------------------------------------------------------- */ void Dumpable::internalAddDumpFieldToDumper(const std::string & dumper_name, const std::string & field_id, dumper::Field * field) { DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.registerField(field_id, field); } /* -------------------------------------------------------------------------- */ DumperIOHelper & Dumpable::getDumper() { return this->getDumper(this->default_dumper); } /* -------------------------------------------------------------------------- */ DumperIOHelper & Dumpable::getDumper(const std::string & dumper_name) { DumperMap::iterator it = this->dumpers.find(dumper_name); DumperMap::iterator end = this->dumpers.end(); if (it == end) AKANTU_EXCEPTION("Dumper " << dumper_name << "has not been registered, yet."); return *(it->second); } /* -------------------------------------------------------------------------- */ std::string Dumpable::getDefaultDumperName() const { return this->default_dumper; } -__END_AKANTU__ +} // akantu #endif diff --git a/src/io/dumper/dumpable_dummy.hh b/src/io/dumper/dumpable_dummy.hh index d955275af..7973056b1 100644 --- a/src/io/dumper/dumpable_dummy.hh +++ b/src/io/dumper/dumpable_dummy.hh @@ -1,252 +1,252 @@ /** * @file dumpable_dummy.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Oct 26 2012 * @date last modification: Fri Aug 21 2015 * * @brief Interface for object who wants to dump themselves * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_DUMPABLE_DUMMY_HH__ #define __AKANTU_DUMPABLE_DUMMY_HH__ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused" namespace dumper { class Field; } class DumperIOHelper; class Mesh; /* -------------------------------------------------------------------------- */ class Dumpable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Dumpable() {}; virtual ~Dumpable() { }; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: template<class T> inline void registerDumper(const std::string & dumper_name, const std::string & file_name = "", const bool is_default = false) { } void registerExternalDumper(DumperIOHelper * dumper, const std::string & dumper_name, const bool is_default = false) { } void addDumpMesh(const Mesh & mesh, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined) { } void addDumpMeshToDumper(const std::string & dumper_name, const Mesh & mesh, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined) { } void addDumpFilteredMesh(const Mesh & mesh, const ElementTypeMapArray<UInt> & elements_filter, const Array<UInt> & nodes_filter, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined) { } void addDumpFilteredMeshToDumper(const std::string & dumper_name, const Mesh & mesh, const ElementTypeMapArray<UInt> & elements_filter, const Array<UInt> & nodes_filter, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined) { } virtual void addDumpField(const std::string & field_id){ AKANTU_DEBUG_TO_IMPLEMENT(); } virtual void addDumpFieldToDumper(const std::string & dumper_name, const std::string & field_id){ AKANTU_DEBUG_TO_IMPLEMENT(); } virtual void addDumpFieldExternal(const std::string & field_id, dumper::Field * field) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } virtual void addDumpFieldExternalToDumper(const std::string & dumper_name, const std::string & field_id, dumper::Field * field) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } template<typename T> void addDumpFieldExternal(const std::string & field_id, const Array<T> & field) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } template<typename T> void addDumpFieldExternalToDumper(const std::string & dumper_name, const std::string & field_id, const Array<T> & field) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } template<typename T> void addDumpFieldExternal(const std::string & field_id, const ElementTypeMapArray<T> & field, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } template<typename T> void addDumpFieldExternalToDumper(const std::string & dumper_name, const std::string & field_id, const ElementTypeMapArray<T> & field, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void removeDumpField(const std::string & field_id) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void removeDumpFieldFromDumper(const std::string & dumper_name, const std::string & field_id) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void setDirectory(const std::string & directory) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void setDirectoryToDumper(const std::string & dumper_name, const std::string & directory) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void setBaseName(const std::string & basename) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void setBaseNameToDumper(const std::string & dumper_name, const std::string & basename) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void setTextModeToDumper(const std::string & dumper_name){ AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void setTextModeToDumper(){ AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void dump() { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void dump(const std::string & dumper_name) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void dump(UInt step) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void dump(const std::string & dumper_name, UInt step) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void dump(Real current_time, UInt step) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void dump(const std::string & dumper_name, Real current_time, UInt step) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } protected: void internalAddDumpFieldToDumper(const std::string & dumper_name, const std::string & field_id, dumper::Field * field) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } protected: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: DumperIOHelper & getDumper() { AKANTU_DEBUG_ERROR("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } DumperIOHelper & getDumper(const std::string & dumper_name){ AKANTU_DEBUG_ERROR("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } template<class T> T & getDumper(const std::string & dumper_name) { AKANTU_DEBUG_ERROR("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } std::string getDefaultDumperName() { AKANTU_DEBUG_ERROR("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; #pragma GCC diagnostic pop -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DUMPABLE_DUMMY_HH__ */ diff --git a/src/io/dumper/dumpable_inline_impl.hh b/src/io/dumper/dumpable_inline_impl.hh index 24e641d36..5406cccbc 100644 --- a/src/io/dumper/dumpable_inline_impl.hh +++ b/src/io/dumper/dumpable_inline_impl.hh @@ -1,134 +1,134 @@ /** * @file dumpable_inline_impl.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Thu Jan 21 2016 * * @brief Implementation of the Dumpable class * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_DUMPABLE_INLINE_IMPL_HH__ #define __AKANTU_DUMPABLE_INLINE_IMPL_HH__ /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER #include "dumper_elemental_field.hh" #include "dumper_nodal_field.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <class T> inline void Dumpable::registerDumper(const std::string & dumper_name, const std::string & file_name, const bool is_default) { if (this->dumpers.find(dumper_name) != this->dumpers.end()) { AKANTU_DEBUG_INFO("Dumper " + dumper_name + "is already registered."); } std::string name = file_name; if (name == "") name = dumper_name; this->dumpers[dumper_name] = new T(name); if (is_default) this->default_dumper = dumper_name; } /* -------------------------------------------------------------------------- */ template <typename T> inline void Dumpable::addDumpFieldExternal(const std::string & field_id, const Array<T> & field) { this->addDumpFieldExternalToDumper<T>(this->default_dumper, field_id, field); } /* -------------------------------------------------------------------------- */ template <typename T> inline void Dumpable::addDumpFieldExternalToDumper(const std::string & dumper_name, const std::string & field_id, const Array<T> & field) { dumper::Field * field_cont = new dumper::NodalField<T>(field); DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.registerField(field_id, field_cont); } /* -------------------------------------------------------------------------- */ template <typename T> inline void Dumpable::addDumpFieldExternal(const std::string & field_id, const ElementTypeMapArray<T> & field, UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & element_kind) { this->addDumpFieldExternalToDumper(this->default_dumper, field_id, field, spatial_dimension, ghost_type, element_kind); } /* -------------------------------------------------------------------------- */ template <typename T> inline void Dumpable::addDumpFieldExternalToDumper( const std::string & dumper_name, const std::string & field_id, const ElementTypeMapArray<T> & field, UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & element_kind) { dumper::Field * field_cont; #if defined(AKANTU_IGFEM) if (element_kind == _ek_igfem) { field_cont = new dumper::IGFEMElementalField<T>(field, spatial_dimension, ghost_type, element_kind); } else #endif field_cont = new dumper::ElementalField<T>(field, spatial_dimension, ghost_type, element_kind); DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.registerField(field_id, field_cont); } /* -------------------------------------------------------------------------- */ template <class T> inline T & Dumpable::getDumper(const std::string & dumper_name) { DumperIOHelper & dumper = this->getDumper(dumper_name); try { T & templated_dumper = dynamic_cast<T &>(dumper); return templated_dumper; } catch (...) { AKANTU_EXCEPTION("Dumper " << dumper_name << " is not of type: " << debug::demangle(typeid(T).name())); } } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #endif #endif /* __AKANTU_DUMPABLE_INLINE_IMPL_HH__ */ diff --git a/src/io/dumper/dumpable_iohelper.hh b/src/io/dumper/dumpable_iohelper.hh index 3d7330154..db0a8ee8c 100644 --- a/src/io/dumper/dumpable_iohelper.hh +++ b/src/io/dumper/dumpable_iohelper.hh @@ -1,195 +1,195 @@ /** * @file dumpable_iohelper.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Jan 06 2015 * @date last modification: Thu Nov 19 2015 * * @brief Interface for object who wants to dump themselves * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_DUMPABLE_IOHELPER_HH__ #define __AKANTU_DUMPABLE_IOHELPER_HH__ /* -------------------------------------------------------------------------- */ #include "dumper_iohelper.hh" #include <set> -__BEGIN_AKANTU__ +namespace akantu { class Dumpable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Dumpable(); virtual ~Dumpable(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// create a new dumper (of templated type T) and register it under /// dumper_name. file_name is used for construction of T. is default states if /// this dumper is the default dumper. template<class T> inline void registerDumper(const std::string & dumper_name, const std::string & file_name = "", const bool is_default = false); /// register an externally created dumper void registerExternalDumper(DumperIOHelper & dumper, const std::string & dumper_name, const bool is_default = false); /// register a mesh to the default dumper void addDumpMesh(const Mesh & mesh, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); /// register a mesh to the default identified by its name void addDumpMeshToDumper(const std::string & dumper_name, const Mesh & mesh, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); /// register a filtered mesh as the default dumper void addDumpFilteredMesh(const Mesh & mesh, const ElementTypeMapArray<UInt> & elements_filter, const Array<UInt> & nodes_filter, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); /// register a filtered mesh and provides a name void addDumpFilteredMeshToDumper(const std::string & dumper_name, const Mesh & mesh, const ElementTypeMapArray<UInt> & elements_filter, const Array<UInt> & nodes_filter, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); /// to implement virtual void addDumpField(const std::string & field_id); /// to implement virtual void addDumpFieldToDumper(const std::string & dumper_name, const std::string & field_id); /// add a field virtual void addDumpFieldExternal(const std::string & field_id, dumper::Field * field); virtual void addDumpFieldExternalToDumper(const std::string & dumper_name, const std::string & field_id, dumper::Field * field); template<typename T> inline void addDumpFieldExternal(const std::string & field_id, const Array<T> & field); template<typename T> inline void addDumpFieldExternalToDumper(const std::string & dumper_name, const std::string & field_id, const Array<T> & field); template<typename T> inline void addDumpFieldExternal(const std::string & field_id, const ElementTypeMapArray<T> & field, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); template<typename T> inline void addDumpFieldExternalToDumper(const std::string & dumper_name, const std::string & field_id, const ElementTypeMapArray<T> & field, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); void removeDumpField(const std::string & field_id); void removeDumpFieldFromDumper(const std::string & dumper_name, const std::string & field_id); virtual void addDumpFieldVector(const std::string & field_id); virtual void addDumpFieldVectorToDumper(const std::string & dumper_name, const std::string & field_id); virtual void addDumpFieldTensor(const std::string & field_id); virtual void addDumpFieldTensorToDumper(const std::string & dumper_name, const std::string & field_id); void setDirectory(const std::string & directory); void setDirectoryToDumper(const std::string & dumper_name, const std::string & directory); void setBaseName(const std::string & basename); void setBaseNameToDumper(const std::string & dumper_name, const std::string & basename); void setTimeStepToDumper(Real time_step); void setTimeStepToDumper(const std::string & dumper_name, Real time_step); void setTextModeToDumper(const std::string & dumper_name); void setTextModeToDumper(); virtual void dump(); virtual void dump(UInt step); virtual void dump(Real time, UInt step); virtual void dump(const std::string & dumper_name); virtual void dump(const std::string & dumper_name, UInt step); virtual void dump(const std::string & dumper_name, Real time, UInt step); public: void internalAddDumpFieldToDumper(const std::string & dumper_name, const std::string & field_id, dumper::Field * field); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: DumperIOHelper & getDumper(); DumperIOHelper & getDumper(const std::string & dumper_name); template<class T> T & getDumper(const std::string & dumper_name); std::string getDefaultDumperName() const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: typedef std::map<std::string, DumperIOHelper *> DumperMap; typedef std::set<std::string> DumperSet; DumperMap dumpers; std::string default_dumper; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DUMPABLE_IOHELPER_HH__ */ diff --git a/src/io/dumper/dumper_compute.hh b/src/io/dumper/dumper_compute.hh index b97c989dc..a55f37291 100644 --- a/src/io/dumper/dumper_compute.hh +++ b/src/io/dumper/dumper_compute.hh @@ -1,272 +1,272 @@ /** * @file dumper_compute.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * * @date creation: Tue Sep 02 2014 * @date last modification: Tue Jan 19 2016 * * @brief Field that map a function to another field * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_DUMPER_COMPUTE_HH__ #define __AKANTU_DUMPER_COMPUTE_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "dumper_iohelper.hh" #include "dumper_type_traits.hh" #include "dumper_field.hh" #include <io_helper.hh> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { __BEGIN_AKANTU_DUMPER__ class ComputeFunctorInterface { public: virtual ~ComputeFunctorInterface(){}; virtual UInt getDim() = 0; virtual UInt getNbComponent(UInt old_nb_comp) = 0; }; /* -------------------------------------------------------------------------- */ template <typename return_type> class ComputeFunctorOutput : public ComputeFunctorInterface { public: ComputeFunctorOutput(){}; virtual ~ComputeFunctorOutput(){}; }; /* -------------------------------------------------------------------------- */ template <typename input_type, typename return_type> class ComputeFunctor : public ComputeFunctorOutput<return_type> { public: ComputeFunctor(){}; virtual ~ComputeFunctor(){}; virtual return_type func(const input_type & d, Element global_index) = 0; }; /* -------------------------------------------------------------------------- */ template <typename SubFieldCompute, typename _return_type> class FieldCompute : public Field { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: typedef typename SubFieldCompute::iterator sub_iterator; typedef typename SubFieldCompute::types sub_types; typedef typename sub_types::return_type sub_return_type; typedef _return_type return_type; typedef typename sub_types::data_type data_type; typedef TypeTraits<data_type, return_type, ElementTypeMapArray<data_type> > types; class iterator { public: iterator(const sub_iterator & it, ComputeFunctor<sub_return_type, return_type> & func) : it(it), func(func) {} bool operator!=(const iterator & it) const { return it.it != this->it; } iterator operator++() { ++this->it; return *this; } UInt currentGlobalIndex() { return this->it.currentGlobalIndex(); } return_type operator*() { return func.func(*it, it.getCurrentElement()); } Element getCurrentElement() { return this->it.getCurrentElement(); } UInt element_type() { return this->it.element_type(); } protected: sub_iterator it; ComputeFunctor<sub_return_type, return_type> & func; }; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FieldCompute(SubFieldCompute & cont, ComputeFunctorInterface & func) : sub_field(cont), func(dynamic_cast<ComputeFunctor<sub_return_type, return_type> &>( func)) { this->checkHomogeneity(); }; ~FieldCompute() { delete &(this->sub_field); delete &(this->func); } virtual void registerToDumper(const std::string & id, iohelper::Dumper & dumper) { dumper.addElemDataField(id, *this); } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: iterator begin() { return iterator(sub_field.begin(), func); } iterator end() { return iterator(sub_field.end(), func); } UInt getDim() { return func.getDim(); } UInt size() { throw; // return Functor::size(); return 0; } virtual void checkHomogeneity() { this->homogeneous = true; }; iohelper::DataType getDataType() { return iohelper::getDataType<data_type>(); } /// get the number of components of the hosted field virtual ElementTypeMap<UInt> getNbComponents(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_not_defined) { ElementTypeMap<UInt> nb_components; const ElementTypeMap<UInt> & old_nb_components = this->sub_field.getNbComponents(dim, ghost_type, kind); ElementTypeMap<UInt>::type_iterator tit = old_nb_components.firstType(dim, ghost_type, kind); ElementTypeMap<UInt>::type_iterator end = old_nb_components.lastType(dim, ghost_type, kind); while (tit != end) { UInt nb_comp = old_nb_components(*tit, ghost_type); nb_components(*tit, ghost_type) = func.getNbComponent(nb_comp); ++tit; } return nb_components; }; /// for connection to a FieldCompute inline virtual Field * connect(FieldComputeProxy & proxy); /// for connection to a FieldCompute virtual ComputeFunctorInterface * connect(HomogenizerProxy & proxy); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: SubFieldCompute & sub_field; ComputeFunctor<sub_return_type, return_type> & func; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ class FieldComputeProxy { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FieldComputeProxy(ComputeFunctorInterface & func) : func(func){}; inline static Field * createFieldCompute(Field * field, ComputeFunctorInterface & func) { /// that looks fishy an object passed as a ref and destroyed at their end of /// the function FieldComputeProxy compute_proxy(func); return field->connect(compute_proxy); } template <typename T> Field * connectToField(T * ptr) { if (dynamic_cast<ComputeFunctorOutput<Vector<Real> > *>(&func)) { return this->connectToFunctor<Vector<Real> >(ptr); } else if (dynamic_cast<ComputeFunctorOutput<Vector<UInt> > *>(&func)) { return this->connectToFunctor<Vector<UInt> >(ptr); } else if (dynamic_cast<ComputeFunctorOutput<Matrix<UInt> > *>(&func)) { return this->connectToFunctor<Matrix<UInt> >(ptr); } else if (dynamic_cast<ComputeFunctorOutput<Matrix<Real> > *>(&func)) { return this->connectToFunctor<Matrix<Real> >(ptr); } else throw; } template <typename output, typename T> Field * connectToFunctor(T * ptr) { FieldCompute<T, output> * functor_ptr = new FieldCompute<T, output>(*ptr, func); return functor_ptr; } template <typename output, typename SubFieldCompute, typename return_type1, typename return_type2> Field * connectToFunctor(__attribute__((unused)) FieldCompute< FieldCompute<SubFieldCompute, return_type1>, return_type2> * ptr) { throw; // return new FieldCompute<T,output>(*ptr,func); return NULL; } template <typename output, typename SubFieldCompute, typename return_type1, typename return_type2, typename return_type3, typename return_type4> Field * connectToFunctor(__attribute__((unused)) FieldCompute< FieldCompute<FieldCompute<FieldCompute<SubFieldCompute, return_type1>, return_type2>, return_type3>, return_type4> * ptr) { throw; // return new FieldCompute<T,output>(*ptr,func); return NULL; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: ComputeFunctorInterface & func; }; /* -------------------------------------------------------------------------- */ /// for connection to a FieldCompute template <typename SubFieldCompute, typename return_type> inline Field * FieldCompute<SubFieldCompute, return_type>::connect(FieldComputeProxy & proxy) { return proxy.connectToField(this); } /* -------------------------------------------------------------------------- */ __END_AKANTU_DUMPER__ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DUMPER_COMPUTE_HH__ */ diff --git a/src/io/dumper/dumper_element_iterator.hh b/src/io/dumper/dumper_element_iterator.hh index d28dd853f..5daeff6b3 100644 --- a/src/io/dumper/dumper_element_iterator.hh +++ b/src/io/dumper/dumper_element_iterator.hh @@ -1,193 +1,193 @@ /** * @file dumper_element_iterator.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Sep 02 2014 * @date last modification: Fri May 15 2015 * * @brief Iterators for elemental fields * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_DUMPER_ELEMENT_ITERATOR_HH__ #define __AKANTU_DUMPER_ELEMENT_ITERATOR_HH__ /* -------------------------------------------------------------------------- */ #include "element.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { __BEGIN_AKANTU_DUMPER__ /* -------------------------------------------------------------------------- */ template<class types, template <class> class final_iterator> class element_iterator { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: typedef typename types::it_type it_type; typedef typename types::field_type field_type; typedef typename types::array_type array_type; typedef typename types::array_iterator array_iterator; typedef final_iterator<types> iterator; public: /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ element_iterator(const field_type & field, const typename field_type::type_iterator & t_it, const typename field_type::type_iterator & t_it_end, const array_iterator & array_it, const array_iterator & array_it_end, const GhostType ghost_type = _not_ghost) : field(field), tit(t_it), tit_end(t_it_end), array_it(array_it), array_it_end(array_it_end), ghost_type(ghost_type) { } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: bool operator!=(const iterator & it) const { return (ghost_type != it.ghost_type) || (tit != it.tit || (array_it != it.array_it)); } iterator & operator++() { ++array_it; while(array_it == array_it_end && tit != tit_end) { ++tit; if(tit != tit_end) { const array_type & vect = field(*tit, ghost_type); UInt _nb_data_per_elem = getNbDataPerElem(*tit); UInt nb_component = vect.getNbComponent(); UInt size = (vect.getSize() * nb_component) / _nb_data_per_elem; array_it = vect.begin_reinterpret(_nb_data_per_elem,size); array_it_end = vect.end_reinterpret (_nb_data_per_elem,size); } } return *(static_cast<iterator *>(this)); }; ElementType getType() { return *tit; } UInt element_type() { return getIOHelperType(*tit); } Element getCurrentElement(){ return Element(*tit,array_it.getCurrentIndex()); } UInt getNbDataPerElem(const ElementType & type) const { if (!nb_data_per_elem.exists(type, ghost_type)) return field(type,ghost_type).getNbComponent(); return nb_data_per_elem(type,ghost_type); } void setNbDataPerElem(const ElementTypeMap<UInt> & nb_data){ this->nb_data_per_elem = nb_data; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// the field to iterate on const field_type & field; /// field iterator typename field_type::type_iterator tit; /// field iterator end typename field_type::type_iterator tit_end; /// array iterator array_iterator array_it; /// internal iterator end array_iterator array_it_end; /// ghost type identification const GhostType ghost_type; /// number of data per element ElementTypeMap<UInt> nb_data_per_elem; }; /* -------------------------------------------------------------------------- */ template<typename types> class elemental_field_iterator : public element_iterator<types, elemental_field_iterator> { public: /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ typedef element_iterator<types, ::akantu::dumper::elemental_field_iterator> parent; typedef typename types::it_type it_type; typedef typename types::return_type return_type; typedef typename types::field_type field_type; typedef typename types::array_iterator array_iterator; public: /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ elemental_field_iterator(const field_type & field, const typename field_type::type_iterator & t_it, const typename field_type::type_iterator & t_it_end, const array_iterator & array_it, const array_iterator & array_it_end, const GhostType ghost_type = _not_ghost) : parent(field, t_it, t_it_end, array_it, array_it_end, ghost_type) { } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ return_type operator*(){ return *this->array_it; } private: }; /* -------------------------------------------------------------------------- */ __END_AKANTU_DUMPER__ -__END_AKANTU__ +} // akantu /* -------------------------------------------------------------------------- */ #endif /* __AKANTU_DUMPER_ELEMENT_ITERATOR_HH__ */ diff --git a/src/io/dumper/dumper_element_partition.hh b/src/io/dumper/dumper_element_partition.hh index a4eb05d66..21296b317 100644 --- a/src/io/dumper/dumper_element_partition.hh +++ b/src/io/dumper/dumper_element_partition.hh @@ -1,124 +1,124 @@ /** * @file dumper_element_partition.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Sep 02 2014 * @date last modification: Tue Jul 14 2015 * * @brief ElementPartition field * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { __BEGIN_AKANTU_DUMPER__ #ifdef AKANTU_IGFEM # include "dumper_igfem_element_partition.hh" #endif /* -------------------------------------------------------------------------- */ template<class types> class element_partition_field_iterator : public element_iterator<types, element_partition_field_iterator> { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: typedef element_iterator<types, dumper::element_partition_field_iterator> parent; typedef typename types::return_type return_type; typedef typename types::array_iterator array_iterator; typedef typename types::field_type field_type; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: element_partition_field_iterator(const field_type & field, const typename field_type::type_iterator & t_it, const typename field_type::type_iterator & t_it_end, const array_iterator & array_it, const array_iterator & array_it_end, const GhostType ghost_type = _not_ghost) : parent(field, t_it, t_it_end, array_it, array_it_end, ghost_type) { prank = StaticCommunicator::getStaticCommunicator().whoAmI(); } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: return_type operator*() { return return_type(1, prank); } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: UInt prank; }; /* -------------------------------------------------------------------------- */ template<bool filtered = false> class ElementPartitionField : public GenericElementalField<SingleType<UInt,Vector,filtered>, element_partition_field_iterator> { public: /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ typedef SingleType<UInt,Vector,filtered> types; typedef element_partition_field_iterator<types> iterator; typedef GenericElementalField<types,element_partition_field_iterator> parent; typedef typename types::field_type field_type; public: /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ ElementPartitionField(const field_type & field, UInt spatial_dimension = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind element_kind = _ek_not_defined) : parent(field, spatial_dimension, ghost_type, element_kind) { this->homogeneous = true; } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ UInt getDim() { return 1; } }; /* -------------------------------------------------------------------------- */ __END_AKANTU_DUMPER__ -__END_AKANTU__ +} // akantu diff --git a/src/io/dumper/dumper_elemental_field.hh b/src/io/dumper/dumper_elemental_field.hh index cec891358..452c277d3 100644 --- a/src/io/dumper/dumper_elemental_field.hh +++ b/src/io/dumper/dumper_elemental_field.hh @@ -1,80 +1,80 @@ /** * @file dumper_elemental_field.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Mon Aug 17 2015 * * @brief description of elemental fields * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_DUMPER_ELEMENTAL_FIELD_HH__ #define __AKANTU_DUMPER_ELEMENTAL_FIELD_HH__ /* -------------------------------------------------------------------------- */ #include "static_communicator.hh" #include "dumper_field.hh" #include "dumper_generic_elemental_field.hh" #ifdef AKANTU_IGFEM # include "dumper_igfem_elemental_field.hh" #endif /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { __BEGIN_AKANTU_DUMPER__ /* -------------------------------------------------------------------------- */ template<typename T, template <class> class ret = Vector,bool filtered = false> class ElementalField : public GenericElementalField<SingleType<T,ret,filtered>, elemental_field_iterator> { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: typedef SingleType<T,ret,filtered> types; typedef typename types::field_type field_type; typedef elemental_field_iterator<types> iterator; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ElementalField(const field_type & field, UInt spatial_dimension = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind element_kind = _ek_not_defined) : GenericElementalField<types,elemental_field_iterator>(field, spatial_dimension, ghost_type, element_kind) { } }; /* -------------------------------------------------------------------------- */ __END_AKANTU_DUMPER__ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DUMPER_ELEMENTAL_FIELD_HH__ */ diff --git a/src/io/dumper/dumper_field.hh b/src/io/dumper/dumper_field.hh index b36fcfae8..7c7170e3f 100644 --- a/src/io/dumper/dumper_field.hh +++ b/src/io/dumper/dumper_field.hh @@ -1,137 +1,137 @@ /** * @file dumper_field.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Sep 02 2014 * @date last modification: Tue Jan 19 2016 * * @brief Common interface for fields * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_DUMPER_FIELD_HH__ #define __AKANTU_DUMPER_FIELD_HH__ /* -------------------------------------------------------------------------- */ #include "dumper_iohelper.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { __BEGIN_AKANTU_DUMPER__ /* -------------------------------------------------------------------------- */ class FieldComputeProxy; class FieldComputeBaseInterface; class ComputeFunctorInterface; class HomogenizerProxy; /* -------------------------------------------------------------------------- */ /// Field interface class Field { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Field() : homogeneous(false) {} virtual ~Field(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: #ifdef AKANTU_USE_IOHELPER /// register this to the provided dumper virtual void registerToDumper(const std::string & id, iohelper::Dumper & dumper) = 0; #endif /// set the number of data per item (used for elements fields at the moment) virtual void setNbData(__attribute__((unused)) UInt nb_data) { AKANTU_DEBUG_TO_IMPLEMENT(); }; /// set the number of data per elem (used for elements fields at the moment) virtual void setNbDataPerElem(__attribute__((unused)) const ElementTypeMap<UInt> & nb_data) { AKANTU_DEBUG_TO_IMPLEMENT(); }; /// set the number of data per elem (used for elements fields at the moment) virtual void setNbDataPerElem(__attribute__((unused)) UInt nb_data) { AKANTU_DEBUG_TO_IMPLEMENT(); }; /// get the number of components of the hosted field virtual ElementTypeMap<UInt> getNbComponents(__attribute__((unused)) UInt dim = _all_dimensions, __attribute__((unused)) GhostType ghost_type = _not_ghost, __attribute__((unused)) ElementKind kind = _ek_not_defined) { throw; }; /// for connection to a FieldCompute inline virtual Field * connect(__attribute__((unused)) FieldComputeProxy & proxy) { throw; }; /// for connection to a FieldCompute inline virtual ComputeFunctorInterface * connect(__attribute__((unused)) HomogenizerProxy & proxy) { throw; }; /// check if the same quantity of data for all element types virtual void checkHomogeneity() = 0; /// return the dumper name std::string getGroupName() { return group_name; }; /// return the id of the field std::string getID() { return field_id; }; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// return the flag to know if the field is homogeneous/contiguous virtual bool isHomogeneous() { return homogeneous; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// the flag to know if it is homogeneous bool homogeneous; /// the name of the group it was associated to std::string group_name; /// the name of the dumper it was associated to std::string field_id; }; /* -------------------------------------------------------------------------- */ __END_AKANTU_DUMPER__ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DUMPER_FIELD_HH__ */ diff --git a/src/io/dumper/dumper_filtered_connectivity.hh b/src/io/dumper/dumper_filtered_connectivity.hh index 9f4f313e7..ebc21227e 100644 --- a/src/io/dumper/dumper_filtered_connectivity.hh +++ b/src/io/dumper/dumper_filtered_connectivity.hh @@ -1,151 +1,151 @@ /** * @file dumper_filtered_connectivity.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Sep 02 2014 * @date last modification: Mon Aug 17 2015 * * @brief FilteredConnectivities field * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #include "dumper_generic_elemental_field.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { __BEGIN_AKANTU_DUMPER__ /* -------------------------------------------------------------------------- */ template <class types> class filtered_connectivity_field_iterator : public element_iterator<types, filtered_connectivity_field_iterator> { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: typedef element_iterator<types, dumper::filtered_connectivity_field_iterator> parent; typedef typename types::return_type return_type; typedef typename types::field_type field_type; typedef typename types::array_iterator array_iterator; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: filtered_connectivity_field_iterator(const field_type & field, const typename field_type::type_iterator & t_it, const typename field_type::type_iterator & t_it_end, const array_iterator & array_it, const array_iterator & array_it_end, const GhostType ghost_type = _not_ghost) : parent(field, t_it, t_it_end, array_it, array_it_end, ghost_type) { } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: return_type operator*(){ const Vector<UInt> & old_connect = *this->array_it; Vector<UInt> new_connect(old_connect.size()); Array<UInt>::const_iterator<UInt> nodes_begin = nodal_filter->begin(); Array<UInt>::const_iterator<UInt> nodes_end = nodal_filter->end(); for(UInt i(0); i<old_connect.size(); ++i) { Array<UInt>::const_iterator<UInt> new_id = std::find(nodes_begin, nodes_end, old_connect(i)); if(new_id == nodes_end) AKANTU_EXCEPTION("Node not found in the filter!"); new_connect(i) = new_id - nodes_begin; } return new_connect; } void setNodalFilter(const Array<UInt> & new_nodal_filter) { nodal_filter = &new_nodal_filter; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: const Array<UInt> * nodal_filter; }; /* -------------------------------------------------------------------------- */ class FilteredConnectivityField : public GenericElementalField<SingleType<UInt,Vector,true>, filtered_connectivity_field_iterator> { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: typedef SingleType<UInt,Vector,true> types; typedef filtered_connectivity_field_iterator<types> iterator; typedef types::field_type field_type; typedef GenericElementalField<types,filtered_connectivity_field_iterator> parent; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FilteredConnectivityField(const field_type & field, const Array<UInt> & nodal_filter, UInt spatial_dimension = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind element_kind = _ek_not_defined) : parent(field, spatial_dimension, ghost_type, element_kind), nodal_filter(nodal_filter) { } ~FilteredConnectivityField() { // since the field is created in registerFilteredMesh it is destroyed here delete const_cast<field_type *>(&this->field); } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: iterator begin() { iterator it = parent::begin(); it.setNodalFilter(nodal_filter); return it; } iterator end() { iterator it = parent::end(); it.setNodalFilter(nodal_filter); return it; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: const Array<UInt> & nodal_filter; }; /* -------------------------------------------------------------------------- */ __END_AKANTU_DUMPER__ -__END_AKANTU__ +} // akantu /* -------------------------------------------------------------------------- */ diff --git a/src/io/dumper/dumper_generic_elemental_field.hh b/src/io/dumper/dumper_generic_elemental_field.hh index e722fc882..da45b65e4 100644 --- a/src/io/dumper/dumper_generic_elemental_field.hh +++ b/src/io/dumper/dumper_generic_elemental_field.hh @@ -1,224 +1,224 @@ /** * @file dumper_generic_elemental_field.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Sep 02 2014 * @date last modification: Tue Jan 19 2016 * * @brief Generic interface for elemental fields * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_DUMPER_GENERIC_ELEMENTAL_FIELD_HH__ #define __AKANTU_DUMPER_GENERIC_ELEMENTAL_FIELD_HH__ /* -------------------------------------------------------------------------- */ #include "dumper_field.hh" #include "element_type_map_filter.hh" #include "dumper_element_iterator.hh" #include "dumper_homogenizing_field.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { __BEGIN_AKANTU_DUMPER__ /* -------------------------------------------------------------------------- */ template <class _types, template <class> class iterator_type> class GenericElementalField : public Field { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: // check dumper_type_traits.hh for additional information over these types typedef _types types; typedef typename types::data_type data_type; typedef typename types::it_type it_type; typedef typename types::field_type field_type; typedef typename types::array_type array_type; typedef typename types::array_iterator array_iterator; typedef typename field_type::type_iterator field_type_iterator; typedef iterator_type<types> iterator; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: GenericElementalField(const field_type & field, UInt spatial_dimension = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind element_kind = _ek_not_defined) : field(field), spatial_dimension(spatial_dimension), ghost_type(ghost_type), element_kind(element_kind) { this->checkHomogeneity(); } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// get the number of components of the hosted field virtual ElementTypeMap<UInt> getNbComponents(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_not_defined) { return this->field.getNbComponents(dim, ghost_type, kind); }; /// return the size of the contained data: i.e. the number of elements ? virtual UInt size() { checkHomogeneity(); return this->nb_total_element; } /// return the iohelper datatype to be dumped iohelper::DataType getDataType() { return iohelper::getDataType<data_type>(); } protected: /// return the number of entries per element UInt getNbDataPerElem(const ElementType & type, const GhostType & ghost_type = _not_ghost) const { if (!nb_data_per_elem.exists(type, ghost_type)) return field(type, ghost_type).getNbComponent(); return nb_data_per_elem(type, this->ghost_type); } /// check if the same quantity of data for all element types virtual void checkHomogeneity(); public: virtual void registerToDumper(const std::string & id, iohelper::Dumper & dumper) { dumper.addElemDataField(id, *this); }; /// for connection to a FieldCompute inline virtual Field * connect(FieldComputeProxy & proxy) { return proxy.connectToField(this); } /// for connection to a Homogenizer inline virtual ComputeFunctorInterface * connect(HomogenizerProxy & proxy) { return proxy.connectToField(this); }; virtual iterator begin() { field_type_iterator tit; field_type_iterator end; /// type iterators on the elemental field tit = this->field.firstType(this->spatial_dimension, this->ghost_type, this->element_kind); end = this->field.lastType(this->spatial_dimension, this->ghost_type, this->element_kind); /// skip all types without data ElementType type = *tit; for (; tit != end && this->field(*tit, this->ghost_type).getSize() == 0; ++tit) { } type = *tit; if (tit == end) return this->end(); /// getting information for the field of the given type const array_type & vect = this->field(type, this->ghost_type); UInt nb_data_per_elem = this->getNbDataPerElem(type); UInt nb_component = vect.getNbComponent(); UInt size = (vect.getSize() * nb_component) / nb_data_per_elem; /// define element-wise iterator array_iterator it = vect.begin_reinterpret(nb_data_per_elem, size); array_iterator it_end = vect.end_reinterpret(nb_data_per_elem, size); /// define data iterator iterator rit = iterator(this->field, tit, end, it, it_end, this->ghost_type); rit.setNbDataPerElem(this->nb_data_per_elem); return rit; } virtual iterator end() { field_type_iterator tit; field_type_iterator end; tit = this->field.firstType(this->spatial_dimension, this->ghost_type, this->element_kind); end = this->field.lastType(this->spatial_dimension, this->ghost_type, this->element_kind); ElementType type = *tit; for (; tit != end; ++tit) type = *tit; const array_type & vect = this->field(type, this->ghost_type); UInt nb_data = this->getNbDataPerElem(type); UInt nb_component = vect.getNbComponent(); UInt size = (vect.getSize() * nb_component) / nb_data; array_iterator it = vect.end_reinterpret(nb_data, size); iterator rit = iterator(this->field, end, end, it, it, this->ghost_type); rit.setNbDataPerElem(this->nb_data_per_elem); return rit; } virtual UInt getDim() { if (this->homogeneous) { field_type_iterator tit = this->field.firstType( this->spatial_dimension, this->ghost_type, this->element_kind); return this->getNbDataPerElem(*tit); } throw; return 0; } void setNbDataPerElem(const ElementTypeMap<UInt> & nb_data) { nb_data_per_elem = nb_data; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// the ElementTypeMapArray embedded in the field const field_type & field; /// total number of elements UInt nb_total_element; /// the spatial dimension of the problem UInt spatial_dimension; /// whether this is a ghost field or not (for type selection) GhostType ghost_type; /// The element kind to operate on ElementKind element_kind; /// The number of data per element type ElementTypeMap<UInt> nb_data_per_elem; }; /* -------------------------------------------------------------------------- */ #include "dumper_generic_elemental_field_tmpl.hh" /* -------------------------------------------------------------------------- */ -__END_AKANTU_DUMPER__ __END_AKANTU__ +__END_AKANTU_DUMPER__ } // akantu #endif /* __AKANTU_DUMPER_GENERIC_ELEMENTAL_FIELD_HH__ */ diff --git a/src/io/dumper/dumper_homogenizing_field.hh b/src/io/dumper/dumper_homogenizing_field.hh index 67308ee7a..ad50139dd 100644 --- a/src/io/dumper/dumper_homogenizing_field.hh +++ b/src/io/dumper/dumper_homogenizing_field.hh @@ -1,217 +1,217 @@ /** * @file dumper_homogenizing_field.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Sep 02 2014 * @date last modification: Tue Jul 14 2015 * * @brief description of field homogenizing field * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_DUMPER_HOMOGENIZING_FIELD_HH__ #define __AKANTU_DUMPER_HOMOGENIZING_FIELD_HH__ /* -------------------------------------------------------------------------- */ #include "dumper_compute.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { __BEGIN_AKANTU_DUMPER__ /* -------------------------------------------------------------------------- */ template <typename type> inline type typeConverter(const type & input, __attribute__((unused)) Vector<typename type::value_type> & res, __attribute__((unused)) UInt nb_data) { throw; return input; } /* -------------------------------------------------------------------------- */ template <typename type> inline Matrix<type> typeConverter(const Matrix<type> & input, Vector<type> & res, UInt nb_data) { Matrix<type> tmp(res.storage(), input.rows(), nb_data / input.rows()); Matrix<type> tmp2(tmp, true); return tmp2; } /* -------------------------------------------------------------------------- */ template <typename type> inline Vector<type> typeConverter(__attribute__((unused)) const Vector<type> & input, __attribute__((unused)) Vector<type> & res, __attribute__((unused)) UInt nb_data) { return res; } /* -------------------------------------------------------------------------- */ template <typename type> class AvgHomogenizingFunctor : public ComputeFunctor<type, type> { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ typedef typename type::value_type value_type; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: AvgHomogenizingFunctor(ElementTypeMap<UInt> & nb_datas) { ElementTypeMap<UInt>::type_iterator tit = nb_datas.firstType(); ElementTypeMap<UInt>::type_iterator end = nb_datas.lastType(); nb_data = nb_datas(*tit); for (; tit != end; ++tit) if (nb_data != nb_datas(*tit)) throw; } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ virtual type func(const type & d, __attribute__((unused)) Element global_index) { Vector<value_type> res(this->nb_data); if (d.size() % this->nb_data) throw; UInt nb_to_average = d.size() / this->nb_data; value_type * ptr = d.storage(); for (UInt i = 0; i < nb_to_average; ++i) { Vector<value_type> tmp(ptr, this->nb_data); res += tmp; ptr += this->nb_data; } res /= nb_to_average; return typeConverter(d, res, this->nb_data); }; UInt getDim() { return nb_data; }; UInt getNbComponent(__attribute__((unused)) UInt old_nb_comp) { throw; }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ /// The size of data: i.e. the size of the vector to be returned UInt nb_data; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ class HomogenizerProxy { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: HomogenizerProxy(){}; public: inline static ComputeFunctorInterface * createHomogenizer(Field & field); template <typename T> inline ComputeFunctorInterface * connectToField(T * field) { ElementTypeMap<UInt> nb_components = field->getNbComponents(); typedef typename T::types::return_type ret_type; return this->instantiateHomogenizer<ret_type>(nb_components); } template <typename ret_type> inline ComputeFunctorInterface * instantiateHomogenizer(ElementTypeMap<UInt> & nb_components); }; /* -------------------------------------------------------------------------- */ template <typename ret_type> inline ComputeFunctorInterface * HomogenizerProxy::instantiateHomogenizer(ElementTypeMap<UInt> & nb_components) { typedef dumper::AvgHomogenizingFunctor<ret_type> Homogenizer; Homogenizer * foo = new Homogenizer(nb_components); return foo; } template <> inline ComputeFunctorInterface * HomogenizerProxy::instantiateHomogenizer<Vector<iohelper::ElemType> >( __attribute__((unused)) ElementTypeMap<UInt> & nb_components) { throw; return NULL; } /* -------------------------------------------------------------------------- */ /// for connection to a FieldCompute template <typename SubFieldCompute, typename return_type> inline ComputeFunctorInterface * FieldCompute<SubFieldCompute, return_type>::connect(HomogenizerProxy & proxy) { return proxy.connectToField(this); } /* -------------------------------------------------------------------------- */ inline ComputeFunctorInterface * HomogenizerProxy::createHomogenizer(Field & field) { HomogenizerProxy homogenizer_proxy; return field.connect(homogenizer_proxy); } /* -------------------------------------------------------------------------- */ // inline ComputeFunctorInterface & createHomogenizer(Field & field){ // HomogenizerProxy::createHomogenizer(field); // throw; // ComputeFunctorInterface * ptr = NULL; // return *ptr; // } // /* -------------------------------------------------------------------------- // */ __END_AKANTU_DUMPER__ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DUMPER_HOMOGENIZING_FIELD_HH__ */ diff --git a/src/io/dumper/dumper_internal_material_field.hh b/src/io/dumper/dumper_internal_material_field.hh index 84c68f24f..72e25e5d2 100644 --- a/src/io/dumper/dumper_internal_material_field.hh +++ b/src/io/dumper/dumper_internal_material_field.hh @@ -1,78 +1,78 @@ /** * @file dumper_internal_material_field.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Sep 17 2015 * * @brief description of material internal field * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_DUMPER_INTERNAL_MATERIAL_FIELD_HH__ #define __AKANTU_DUMPER_INTERNAL_MATERIAL_FIELD_HH__ /* -------------------------------------------------------------------------- */ #include "dumper_quadrature_point_iterator.hh" #ifdef AKANTU_IGFEM # include "dumper_igfem_material_internal_field.hh" #endif /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { __BEGIN_AKANTU_DUMPER__ /* -------------------------------------------------------------------------- */ template<typename T, bool filtered = false> class InternalMaterialField : public GenericElementalField<SingleType<T,Vector,filtered>, quadrature_point_iterator> { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: typedef SingleType<T,Vector,filtered> types; typedef GenericElementalField<types,quadrature_point_iterator> parent; typedef typename types::field_type field_type; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ InternalMaterialField(const field_type & field, UInt spatial_dimension = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind element_kind = _ek_not_defined) : parent(field, spatial_dimension, ghost_type, element_kind){} }; __END_AKANTU_DUMPER__ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DUMPER_INTERNAL_MATERIAL_FIELD_HH__ */ diff --git a/src/io/dumper/dumper_iohelper.cc b/src/io/dumper/dumper_iohelper.cc index 542e7f91e..124f17255 100644 --- a/src/io/dumper/dumper_iohelper.cc +++ b/src/io/dumper/dumper_iohelper.cc @@ -1,302 +1,302 @@ /** * @file dumper_iohelper.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Dana Christen <dana.christen@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Oct 26 2012 * @date last modification: Thu Sep 17 2015 * * @brief implementation of DumperIOHelper * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <io_helper.hh> #include "dumper_iohelper.hh" #include "dumper_elemental_field.hh" #include "dumper_nodal_field.hh" #include "dumper_filtered_connectivity.hh" #include "dumper_variable.hh" #include "mesh.hh" #if defined(AKANTU_IGFEM) #include "dumper_igfem_connectivity.hh" #endif /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ DumperIOHelper::DumperIOHelper() : count(0), time_activated(false) {} /* -------------------------------------------------------------------------- */ DumperIOHelper::~DumperIOHelper() { for (Fields::iterator it = fields.begin(); it != fields.end(); ++it) { delete it->second; } delete dumper; } /* -------------------------------------------------------------------------- */ void DumperIOHelper::setParallelContext(bool is_parallel) { UInt whoami = StaticCommunicator::getStaticCommunicator().whoAmI(); UInt nb_proc = StaticCommunicator::getStaticCommunicator().getNbProc(); if(is_parallel) dumper->setParallelContext(whoami, nb_proc); else dumper->setParallelContext(0, 1); } /* -------------------------------------------------------------------------- */ void DumperIOHelper::setDirectory(const std::string & directory) { this->directory = directory; dumper->setPrefix(directory); } /* -------------------------------------------------------------------------- */ void DumperIOHelper::setBaseName(const std::string & basename) { filename = basename; } /* -------------------------------------------------------------------------- */ void DumperIOHelper::setTimeStep(Real time_step) { if(!time_activated) this->dumper->activateTimeDescFiles(time_step); else this->dumper->setTimeStep(time_step); } /* -------------------------------------------------------------------------- */ void DumperIOHelper::dump() { try { dumper->dump(filename, count); } catch (iohelper::IOHelperException & e) { AKANTU_DEBUG_ERROR("I was not able to dump your data with a Dumper: " << e.what()); } ++count; } /* -------------------------------------------------------------------------- */ void DumperIOHelper::dump(UInt step) { this->count = step; this->dump(); } /* -------------------------------------------------------------------------- */ void DumperIOHelper::dump(Real current_time, UInt step) { this->dumper->setCurrentTime(current_time); this->dump(step); } /* -------------------------------------------------------------------------- */ void DumperIOHelper::registerMesh(const Mesh & mesh, UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & element_kind) { #if defined(AKANTU_IGFEM) if (element_kind == _ek_igfem) { registerField("connectivities", new dumper::IGFEMConnectivityField(mesh.getConnectivities(), spatial_dimension, ghost_type)); } else #endif registerField("connectivities", new dumper::ElementalField<UInt>(mesh.getConnectivities(), spatial_dimension, ghost_type, element_kind)); registerField("positions", new dumper::NodalField<Real>(mesh.getNodes())); } /* -------------------------------------------------------------------------- */ void DumperIOHelper::registerFilteredMesh(const Mesh & mesh, const ElementTypeMapArray<UInt> & elements_filter, const Array<UInt> & nodes_filter, UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & element_kind) { ElementTypeMapArrayFilter<UInt> * f_connectivities = new ElementTypeMapArrayFilter<UInt>(mesh.getConnectivities(), elements_filter); this->registerField("connectivities", new dumper::FilteredConnectivityField(*f_connectivities, nodes_filter, spatial_dimension, ghost_type, element_kind)); this->registerField("positions",new dumper::NodalField<Real,true>( mesh.getNodes(), 0, 0, &nodes_filter)); } /* -------------------------------------------------------------------------- */ void DumperIOHelper::registerField(const std::string & field_id, dumper::Field * field) { Fields::iterator it = fields.find(field_id); if(it != fields.end()) { AKANTU_DEBUG_WARNING("The field " << field_id << " is already registered in this Dumper. Field ignored."); return; } fields[field_id] = field; field->registerToDumper(field_id, *dumper); } /* -------------------------------------------------------------------------- */ void DumperIOHelper::unRegisterField(const std::string & field_id) { Fields::iterator it = fields.find(field_id); if(it == fields.end()) { AKANTU_DEBUG_WARNING("The field " << field_id << " is not registered in this Dumper. Nothing to do."); return; } delete it->second; fields.erase(it); } /* -------------------------------------------------------------------------- */ void DumperIOHelper::registerVariable(const std::string & variable_id, dumper::VariableBase * variable) { Variables::iterator it = variables.find(variable_id); if(it != variables.end()) { AKANTU_DEBUG_WARNING("The Variable " << variable_id << " is already registered in this Dumper. Variable ignored."); return; } variables[variable_id] = variable; variable->registerToDumper(variable_id, *dumper); } /* -------------------------------------------------------------------------- */ void DumperIOHelper::unRegisterVariable(const std::string & variable_id) { Variables::iterator it = variables.find(variable_id); if(it == variables.end()) { AKANTU_DEBUG_WARNING("The variable " << variable_id << " is not registered in this Dumper. Nothing to do."); return; } delete it->second; variables.erase(it); } /* -------------------------------------------------------------------------- */ template <ElementType type> iohelper::ElemType getIOHelperType() { AKANTU_DEBUG_TO_IMPLEMENT(); return iohelper::MAX_ELEM_TYPE; } template <> iohelper::ElemType getIOHelperType<_point_1>() { return iohelper::POINT_SET; } template <> iohelper::ElemType getIOHelperType<_segment_2>() { return iohelper::LINE1; } template <> iohelper::ElemType getIOHelperType<_segment_3>() { return iohelper::LINE2; } template <> iohelper::ElemType getIOHelperType<_triangle_3>() { return iohelper::TRIANGLE1; } template <> iohelper::ElemType getIOHelperType<_triangle_6>() { return iohelper::TRIANGLE2; } template <> iohelper::ElemType getIOHelperType<_quadrangle_4>() { return iohelper::QUAD1; } template <> iohelper::ElemType getIOHelperType<_quadrangle_8>() { return iohelper::QUAD2; } template <> iohelper::ElemType getIOHelperType<_tetrahedron_4>() { return iohelper::TETRA1; } template <> iohelper::ElemType getIOHelperType<_tetrahedron_10>() { return iohelper::TETRA2; } template <> iohelper::ElemType getIOHelperType<_hexahedron_8>() { return iohelper::HEX1; } template <> iohelper::ElemType getIOHelperType<_hexahedron_20>() { return iohelper::HEX2; } template <> iohelper::ElemType getIOHelperType<_pentahedron_6>() { return iohelper::PRISM1; } template <> iohelper::ElemType getIOHelperType<_pentahedron_15>() { return iohelper::PRISM2; } #if defined(AKANTU_COHESIVE_ELEMENT) template <> iohelper::ElemType getIOHelperType<_cohesive_2d_4>() { return iohelper::COH2D4; } template <> iohelper::ElemType getIOHelperType<_cohesive_2d_6>() { return iohelper::COH2D6; } template <> iohelper::ElemType getIOHelperType<_cohesive_3d_6>() { return iohelper::COH3D6; } template <> iohelper::ElemType getIOHelperType<_cohesive_3d_12>() { return iohelper::COH3D12; } template <> iohelper::ElemType getIOHelperType<_cohesive_3d_8>() { return iohelper::COH3D8; } //template <> //iohelper::ElemType getIOHelperType<_cohesive_3d_16>() { return iohelper::COH3D16; } #endif #if defined(AKANTU_STRUCTURAL_MECHANICS) template <> iohelper::ElemType getIOHelperType<_bernoulli_beam_2>() { return iohelper::BEAM2; } template <> iohelper::ElemType getIOHelperType<_bernoulli_beam_3>() { return iohelper::BEAM3; } #endif /* -------------------------------------------------------------------------- */ UInt getIOHelperType(ElementType type) { UInt ioh_type = iohelper::MAX_ELEM_TYPE; #define GET_IOHELPER_TYPE(type) \ ioh_type = getIOHelperType<type>(); AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_IOHELPER_TYPE); #undef GET_IOHELPER_TYPE return ioh_type; } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu namespace iohelper { template<> DataType getDataType<akantu::NodeType>() { return _int; } } diff --git a/src/io/dumper/dumper_iohelper.hh b/src/io/dumper/dumper_iohelper.hh index 0c75b299e..6ff00d584 100644 --- a/src/io/dumper/dumper_iohelper.hh +++ b/src/io/dumper/dumper_iohelper.hh @@ -1,158 +1,158 @@ /** * @file dumper_iohelper.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Dana Christen <dana.christen@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Oct 26 2012 * @date last modification: Tue Jan 19 2016 * * @brief Define the akantu dumper interface for IOhelper dumpers * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_types.hh" #include "aka_array.hh" #include "element_type_map.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_DUMPER_IOHELPER_HH__ #define __AKANTU_DUMPER_IOHELPER_HH__ /* -------------------------------------------------------------------------- */ namespace iohelper { class Dumper; } -__BEGIN_AKANTU__ +namespace akantu { UInt getIOHelperType(ElementType type); namespace dumper { class Field; class VariableBase; } class Mesh; class DumperIOHelper { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: DumperIOHelper(); virtual ~DumperIOHelper(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// register a given Mesh for the current dumper virtual void registerMesh(const Mesh & mesh, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); /// register a filtered Mesh (provided filter lists) for the current dumper virtual void registerFilteredMesh(const Mesh & mesh, const ElementTypeMapArray<UInt> & elements_filter, const Array<UInt> & nodes_filter, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); /// register a Field object identified by name and provided by pointer void registerField(const std::string & field_id, dumper::Field * field); /// remove the Field identified by name from managed fields void unRegisterField(const std::string & field_id); /// register a VariableBase object identified by name and provided by pointer void registerVariable(const std::string & variable_id, dumper::VariableBase * variable); /// remove a VariableBase identified by name from managed fields void unRegisterVariable(const std::string & variable_id); /// request dump: this calls IOHelper dump routine virtual void dump(); /// request dump: this first set the current step and then calls IOHelper dump /// routine virtual void dump(UInt step); /// request dump: this first set the current step and current time and then /// calls IOHelper dump routine virtual void dump(Real current_time, UInt step); /// set the parallel context for IOHeper virtual void setParallelContext(bool is_parallel); /// set the directory where to generate the dumped files virtual void setDirectory(const std::string & directory); /// set the base name (needed by most IOHelper dumpers) virtual void setBaseName(const std::string & basename); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// direct access to the iohelper::Dumper object AKANTU_GET_MACRO(Dumper, *dumper, iohelper::Dumper &) /// set the timestep of the iohelper::Dumper void setTimeStep(Real time_step); public: /* ------------------------------------------------------------------------ */ /* Variable wrapper */ template <typename T, bool is_scal = is_scalar<T>::value> class Variable; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// internal iohelper::Dumper iohelper::Dumper * dumper; typedef std::map<std::string, dumper::Field *> Fields; typedef std::map<std::string, dumper::VariableBase *> Variables; /// list of registered fields to dump Fields fields; Variables variables; /// dump counter UInt count; /// directory name std::string directory; /// filename prefix std::string filename; /// is time tracking activated in the dumper bool time_activated; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DUMPER_IOHELPER_HH__ */ diff --git a/src/io/dumper/dumper_material_padders.hh b/src/io/dumper/dumper_material_padders.hh index cb9c3546a..bb49ff18e 100644 --- a/src/io/dumper/dumper_material_padders.hh +++ b/src/io/dumper/dumper_material_padders.hh @@ -1,297 +1,297 @@ /** * @file dumper_material_padders.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue Sep 02 2014 * @date last modification: Fri Mar 27 2015 * * @brief Material padders for plane stress/ plane strain * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_DUMPER_MATERIAL_PADDERS_HH__ #define __AKANTU_DUMPER_MATERIAL_PADDERS_HH__ /* -------------------------------------------------------------------------- */ #include "dumper_padding_helper.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { __BEGIN_AKANTU_DUMPER__ /* -------------------------------------------------------------------------- */ class MaterialFunctor { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialFunctor(const SolidMechanicsModel & model) : model(model), material_index(model.getMaterialByElement()), nb_data_per_element("nb_data_per_element", model.getID(), model.getMemoryID()), spatial_dimension(model.getSpatialDimension()){} /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ /// return the material from the global element index const Material & getMaterialFromGlobalIndex(Element global_index) { UInt index = global_index.getIndex(); UInt material_id = material_index(global_index.getType())(index); const Material & material = model.getMaterial(material_id); return material; } /// return the type of the element from global index ElementType getElementTypeFromGlobalIndex(Element global_index) { return global_index.getType(); } protected: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ /// all material padders probably need access to solid mechanics model const SolidMechanicsModel & model; /// they also need an access to the map from global ids to material id and /// local ids const ElementTypeMapArray<UInt> & material_index; /// the number of data per element const ElementTypeMapArray<UInt> nb_data_per_element; UInt spatial_dimension; }; /* -------------------------------------------------------------------------- */ template <class T, class R> class MaterialPadder : public MaterialFunctor, public PadderGeneric<Vector<T>, R> { public: MaterialPadder(const SolidMechanicsModel & model) : MaterialFunctor(model) {} }; /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> class StressPadder : public MaterialPadder<Real, Matrix<Real> > { public: StressPadder(const SolidMechanicsModel & model) : MaterialPadder<Real, Matrix<Real> >(model) { this->setPadding(3, 3); } inline Matrix<Real> func(const Vector<Real> & in, Element global_element_id) { UInt nrows = spatial_dimension; UInt ncols = in.size() / nrows; UInt nb_data = in.size() / (nrows * nrows); Matrix<Real> stress = this->pad(in, nrows, ncols, nb_data); const Material & material = this->getMaterialFromGlobalIndex(global_element_id); bool plane_strain = true; if (spatial_dimension == 2) plane_strain = !((bool) material.getParam("Plane_Stress")); if (plane_strain) { Real nu = material.getParam("nu"); for (UInt d = 0; d < nb_data; ++d) { stress(2, 2 + 3 * d) = nu * (stress(0, 0 + 3 * d) + stress(1, 1 + 3 * d)); } } return stress; } UInt getDim() { return 9; }; UInt getNbComponent(__attribute__((unused)) UInt old_nb_comp) { return this->getDim(); }; }; /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> class StrainPadder : public MaterialFunctor, public PadderGeneric<Matrix<Real>, Matrix<Real> > { public: StrainPadder(const SolidMechanicsModel & model) : MaterialFunctor(model) { this->setPadding(3, 3); } inline Matrix<Real> func(const Matrix<Real> & in, Element global_element_id) { UInt nrows = spatial_dimension; UInt nb_data = in.size() / (nrows * nrows); Matrix<Real> strain = this->pad(in, nb_data); const Material & material = this->getMaterialFromGlobalIndex(global_element_id); bool plane_stress = material.getParam("Plane_Stress"); if (plane_stress) { Real nu = material.getParam("nu"); for (UInt d = 0; d < nb_data; ++d) { strain(2, 2 + 3 * d) = nu / (nu - 1) * (strain(0, 0 + 3 * d) + strain(1, 1 + 3 * d)); } } return strain; } UInt getDim() { return 9; }; UInt getNbComponent(__attribute__((unused)) UInt old_nb_comp) { return this->getDim(); }; }; /* -------------------------------------------------------------------------- */ template <bool green_strain> class ComputeStrain : public MaterialFunctor, public ComputeFunctor<Vector<Real>, Matrix<Real> > { public: ComputeStrain(const SolidMechanicsModel & model) : MaterialFunctor(model) {} inline Matrix<Real> func(const Vector<Real> & in, __attribute__((unused)) Element global_element_id) { UInt nrows = spatial_dimension; UInt ncols = in.size() / nrows; UInt nb_data = in.size() / (nrows * nrows); Matrix<Real> ret_all_strain(nrows, ncols); Tensor3<Real> all_grad_u(in.storage(), nrows, nrows, nb_data); Tensor3<Real> all_strain(ret_all_strain.storage(), nrows, nrows, nb_data); for (UInt d = 0; d < nb_data; ++d) { Matrix<Real> grad_u = all_grad_u(d); Matrix<Real> strain = all_strain(d); if (spatial_dimension == 2) { if (green_strain) Material::gradUToGreenStrain<2>(grad_u, strain); else Material::gradUToEpsilon<2>(grad_u, strain); } else if (spatial_dimension == 3) { if (green_strain) Material::gradUToGreenStrain<3>(grad_u, strain); else Material::gradUToEpsilon<3>(grad_u, strain); } } return ret_all_strain; } UInt getDim() { return spatial_dimension * spatial_dimension; }; UInt getNbComponent(__attribute__((unused)) UInt old_nb_comp) { return this->getDim(); }; }; /* -------------------------------------------------------------------------- */ template <bool green_strain> class ComputePrincipalStrain : public MaterialFunctor, public ComputeFunctor<Vector<Real>, Matrix<Real> > { public: ComputePrincipalStrain(const SolidMechanicsModel & model) : MaterialFunctor(model) {} inline Matrix<Real> func(const Vector<Real> & in, __attribute__((unused)) Element global_element_id) { UInt nrows = spatial_dimension; UInt nb_data = in.size() / (nrows * nrows); Matrix<Real> ret_all_strain(nrows, nb_data); Tensor3<Real> all_grad_u(in.storage(), nrows, nrows, nb_data); Matrix<Real> strain(nrows, nrows); for (UInt d = 0; d < nb_data; ++d) { Matrix<Real> grad_u = all_grad_u(d); if (spatial_dimension == 2) { if (green_strain) Material::gradUToGreenStrain<2>(grad_u, strain); else Material::gradUToEpsilon<2>(grad_u, strain); } else if (spatial_dimension == 3) { if (green_strain) Material::gradUToGreenStrain<3>(grad_u, strain); else Material::gradUToEpsilon<3>(grad_u, strain); } Vector<Real> principal_strain(ret_all_strain(d)); strain.eig(principal_strain); } return ret_all_strain; } UInt getDim() { return spatial_dimension; }; UInt getNbComponent(__attribute__((unused)) UInt old_nb_comp) { return this->getDim(); }; }; /* -------------------------------------------------------------------------- */ class ComputeVonMisesStress : public MaterialFunctor, public ComputeFunctor<Vector<Real>, Vector<Real> > { public: ComputeVonMisesStress(const SolidMechanicsModel & model) : MaterialFunctor(model) {} inline Vector<Real> func(const Vector<Real> & in, __attribute__((unused)) Element global_element_id) { UInt nrows = spatial_dimension; UInt nb_data = in.size() / (nrows * nrows); Vector<Real> von_mises_stress(nb_data); Matrix<Real> deviatoric_stress(3, 3); for (UInt d = 0; d < nb_data; ++d) { Matrix<Real> cauchy_stress(in.storage() + d * nrows * nrows, nrows, nrows); von_mises_stress(d) = Material::stressToVonMises(cauchy_stress); } return von_mises_stress; } UInt getDim() { return 1; }; UInt getNbComponent(__attribute__((unused)) UInt old_nb_comp) { return this->getDim(); }; }; /* -------------------------------------------------------------------------- */ __END_AKANTU_DUMPER__ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DUMPER_MATERIAL_PADDERS_HH__ */ diff --git a/src/io/dumper/dumper_nodal_field.hh b/src/io/dumper/dumper_nodal_field.hh index 86ce33f9d..ead527197 100644 --- a/src/io/dumper/dumper_nodal_field.hh +++ b/src/io/dumper/dumper_nodal_field.hh @@ -1,240 +1,240 @@ /** * @file dumper_nodal_field.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Oct 26 2012 * @date last modification: Tue Jan 06 2015 * * @brief Description of nodal fields * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_DUMPER_NODAL_FIELD_HH__ #define __AKANTU_DUMPER_NODAL_FIELD_HH__ #include "dumper_field.hh" #include <io_helper.hh> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { __BEGIN_AKANTU_DUMPER__ // This represents a iohelper compatible field template<typename T, bool filtered = false, class Container = Array<T>, class Filter = Array<UInt> > class NodalField; /* -------------------------------------------------------------------------- */ template<typename T, class Container, class Filter> class NodalField<T, false, Container, Filter> : public dumper::Field { public: /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ /// associated iterator with any nodal field (non filetered) class iterator : public iohelper::iterator< T, iterator, Vector<T> > { public: iterator(T * vect, UInt offset, UInt n, UInt stride, __attribute__ ((unused)) const UInt * filter = NULL) : internal_it(vect), offset(offset), n(n), stride(stride) {} bool operator!=(const iterator & it) const { return internal_it != it.internal_it; } iterator & operator++() { internal_it += offset; return *this; }; Vector<T> operator* (){ return Vector<T>(internal_it + stride, n); }; private: T * internal_it; UInt offset, n, stride; }; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ NodalField(const Container & field, UInt n = 0, UInt stride = 0, __attribute__ ((unused)) const Filter * filter = NULL) : field(field), n(n), stride(stride), padding(0) { AKANTU_DEBUG_ASSERT(filter == NULL, "Filter passed to unfiltered NodalField!"); if(n == 0) { this->n = field.getNbComponent() - stride; } } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ virtual void registerToDumper(const std::string & id, iohelper::Dumper & dumper) { dumper.addNodeDataField(id, *this); } inline iterator begin() { return iterator(field.storage(), field.getNbComponent(), n, stride); } inline iterator end () { return iterator(field.storage() + field.getNbComponent()*field.getSize(), field.getNbComponent(), n, stride); } bool isHomogeneous() { return true; } void checkHomogeneity() { this->homogeneous = true; } virtual UInt getDim() { if(this->padding) return this->padding; else return n; } void setPadding(UInt padding){this->padding = padding;} UInt size() { return field.getSize(); } iohelper::DataType getDataType() { return iohelper::getDataType<T>(); } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: const Container & field; UInt n, stride; UInt padding; }; /* -------------------------------------------------------------------------- */ template<typename T, class Container, class Filter> class NodalField<T, true, Container, Filter> : public dumper::Field { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: class iterator : public iohelper::iterator< T, iterator, Vector<T> > { public: iterator(T * const vect, UInt _offset, UInt _n, UInt _stride, const UInt * filter) : internal_it(vect), offset(_offset), n(_n), stride(_stride), filter(filter) {} bool operator!=(const iterator & it) const { return filter != it.filter; } iterator & operator++() { ++filter; return *this; } Vector<T> operator* () { return Vector<T>(internal_it + *(filter)*offset + stride, n); } private: T * const internal_it; UInt offset, n, stride; const UInt * filter; }; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ NodalField(const Container & _field, UInt _n = 0, UInt _stride = 0, const Filter * filter = NULL) : field(_field), n(_n), stride(_stride), filter(filter), padding(0) { AKANTU_DEBUG_ASSERT(this->filter != NULL, "No filter passed to filtered NodalField!"); AKANTU_DEBUG_ASSERT(this->filter->getNbComponent()==1, "Multi-component filter given to NodalField (" << this->filter->getNbComponent() << " components detected, sould be 1"); if(n == 0) { this->n = field.getNbComponent() - stride; } } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ virtual void registerToDumper(const std::string & id, iohelper::Dumper & dumper) { dumper.addNodeDataField(id, *this); } inline iterator begin() { return iterator(field.storage(), field.getNbComponent(), n, stride, filter->storage()); } inline iterator end() { return iterator(field.storage(), field.getNbComponent(), n, stride, filter->storage()+filter->getSize()); } bool isHomogeneous() { return true; } void checkHomogeneity() { this->homogeneous = true; } virtual UInt getDim() { if(this->padding) return this->padding; else return n; } void setPadding(UInt padding){this->padding = padding;} UInt size() { return filter->getSize(); } iohelper::DataType getDataType() { return iohelper::getDataType<T>(); } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: const Container & field; UInt n, stride; const Filter * filter; UInt padding; }; __END_AKANTU_DUMPER__ -__END_AKANTU__ +} // akantu /* -------------------------------------------------------------------------- */ #endif /* __AKANTU_DUMPER_NODAL_FIELD_HH__ */ diff --git a/src/io/dumper/dumper_padding_helper.hh b/src/io/dumper/dumper_padding_helper.hh index 7c99fed0e..f36ea33c3 100644 --- a/src/io/dumper/dumper_padding_helper.hh +++ b/src/io/dumper/dumper_padding_helper.hh @@ -1,147 +1,147 @@ /** * @file dumper_padding_helper.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Sep 02 2014 * @date last modification: Sun Oct 19 2014 * * @brief Padding helper for field iterators * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_DUMPER_PADDING_HELPER_HH__ #define __AKANTU_DUMPER_PADDING_HELPER_HH__ /* -------------------------------------------------------------------------- */ #include "dumper_compute.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { __BEGIN_AKANTU_DUMPER__ /* -------------------------------------------------------------------------- */ class PadderInterface { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: PadderInterface(){ padding_m = 0; padding_n = 0; } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void setPadding(UInt m, UInt n = 0){ padding_m = m; padding_n = n; } virtual UInt getPaddedDim(UInt nb_data) { return nb_data; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: /// padding informations UInt padding_n, padding_m; }; /* -------------------------------------------------------------------------- */ template<class input_type, class output_type> class PadderGeneric : public ComputeFunctor<input_type, output_type > , public PadderInterface { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: PadderGeneric() : PadderInterface(){} /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: inline output_type pad(const input_type & in,__attribute__((unused)) UInt nb_data) { return in; // trick due to the fact that IOHelper padds the vectors (avoid a copy of data) } }; /* -------------------------------------------------------------------------- */ template<class T> class PadderGeneric<Vector<T>, Matrix<T> > : public ComputeFunctor<Vector<T>, Matrix<T> > , public PadderInterface { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: inline Matrix<T> pad(const Vector<T> & _in, UInt nrows, UInt ncols, UInt nb_data) { Matrix<T> in(_in.storage(), nrows, ncols); if(padding_m <= nrows && padding_n*nb_data <= ncols) return in; else { Matrix<T> ret(padding_m, padding_n * nb_data); UInt nb_cols_per_data = in.cols() / nb_data; for (UInt d = 0; d < nb_data; ++d) for (UInt i = 0; i < in.rows(); ++i) for (UInt j = 0; j < nb_cols_per_data; ++j) ret(i, j + d * padding_n) = in(i, j + d * nb_cols_per_data); return ret; } } }; /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu __END_AKANTU_DUMPER__ #endif /* __AKANTU_DUMPER_PADDING_HELPER_HH__ */ diff --git a/src/io/dumper/dumper_paraview.cc b/src/io/dumper/dumper_paraview.cc index 5801c0e84..51bb948ef 100644 --- a/src/io/dumper/dumper_paraview.cc +++ b/src/io/dumper/dumper_paraview.cc @@ -1,67 +1,67 @@ /** * @file dumper_paraview.cc * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sun Sep 26 2010 * @date last modification: Sun Oct 19 2014 * * @brief implementations of DumperParaview * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <io_helper.hh> #include "dumper_paraview.hh" #include "static_communicator.hh" #include <fstream> -__BEGIN_AKANTU__ +namespace akantu { DumperParaview::DumperParaview(const std::string & filename, const std::string & directory, bool parallel) : DumperIOHelper() { iohelper::DumperParaview * dumper_para = new iohelper::DumperParaview(); dumper = dumper_para; setBaseName(filename); this->setParallelContext(parallel); dumper_para->setMode(iohelper::BASE64); dumper_para->setPrefix(directory); dumper_para->init(); } /* -------------------------------------------------------------------------- */ DumperParaview::~DumperParaview() { } /* -------------------------------------------------------------------------- */ void DumperParaview::setBaseName(const std::string & basename) { DumperIOHelper::setBaseName(basename); static_cast<iohelper::DumperParaview*>(dumper)->setVTUSubDirectory(filename + "-VTU"); } -__END_AKANTU__ +} // akantu diff --git a/src/io/dumper/dumper_paraview.hh b/src/io/dumper/dumper_paraview.hh index 81812ea5f..448fd2ee3 100644 --- a/src/io/dumper/dumper_paraview.hh +++ b/src/io/dumper/dumper_paraview.hh @@ -1,74 +1,74 @@ /** * @file dumper_paraview.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief Dumper Paraview using IOHelper * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_DUMPER_PARAVIEW_HH__ #define __AKANTU_DUMPER_PARAVIEW_HH__ #include "dumper_iohelper.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class DumperParaview : public DumperIOHelper { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: DumperParaview(const std::string & filename, const std::string & directory = "./paraview", bool parallel = true); virtual ~DumperParaview(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: // void dump(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: void setBaseName(const std::string & basename); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DUMPER_PARAVIEW_HH__ */ diff --git a/src/io/dumper/dumper_quadrature_point_iterator.hh b/src/io/dumper/dumper_quadrature_point_iterator.hh index 7c740aa4e..2bd3f6699 100644 --- a/src/io/dumper/dumper_quadrature_point_iterator.hh +++ b/src/io/dumper/dumper_quadrature_point_iterator.hh @@ -1,77 +1,77 @@ /** * @file dumper_quadrature_point_iterator.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Sep 02 2014 * @date last modification: Thu Sep 17 2015 * * @brief Description of quadrature point iterator * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_DUMPER_QUADRATURE_POINT_ITERATOR_HH__ #define __AKANTU_DUMPER_QUADRATURE_POINT_ITERATOR_HH__ /* -------------------------------------------------------------------------- */ #include "dumper_elemental_field.hh" -__BEGIN_AKANTU__ +namespace akantu { __BEGIN_AKANTU_DUMPER__ /* -------------------------------------------------------------------------- */ template<typename types> class quadrature_point_iterator : public element_iterator<types, quadrature_point_iterator> { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: typedef element_iterator<types, dumper::quadrature_point_iterator> parent; typedef typename types::data_type data_type; typedef typename types::return_type return_type; typedef typename types::field_type field_type; typedef typename types::array_iterator array_iterator; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: quadrature_point_iterator(const field_type & field, const typename field_type::type_iterator & t_it, const typename field_type::type_iterator & t_it_end, const array_iterator & array_it, const array_iterator & array_it_end, const GhostType ghost_type = _not_ghost) : parent(field, t_it, t_it_end, array_it, array_it_end, ghost_type) { } return_type operator*() { return *this->array_it; } }; /* -------------------------------------------------------------------------- */ __END_AKANTU_DUMPER__ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DUMPER_QUADRATURE_POINT_ITERATOR_HH__ */ diff --git a/src/io/dumper/dumper_text.cc b/src/io/dumper/dumper_text.cc index df3ae7a48..a06258cc5 100644 --- a/src/io/dumper/dumper_text.cc +++ b/src/io/dumper/dumper_text.cc @@ -1,113 +1,113 @@ /** * @file dumper_text.cc * * @author David Simon Kammer <david.kammer@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief implementation of text dumper * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <io_helper.hh> #include "dumper_text.hh" #include "dumper_nodal_field.hh" #include "mesh.hh" #include "static_communicator.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ DumperText::DumperText(const std::string & basename, iohelper::TextDumpMode mode, bool parallel) : DumperIOHelper() { AKANTU_DEBUG_IN(); iohelper::DumperText * dumper_text = new iohelper::DumperText(mode); this->dumper = dumper_text; this->setBaseName(basename); this->setParallelContext(parallel); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void DumperText::registerMesh(const Mesh & mesh, __attribute__((unused)) UInt spatial_dimension, __attribute__((unused)) const GhostType & ghost_type, __attribute__((unused)) const ElementKind & element_kind) { registerField("position", new dumper::NodalField<Real>(mesh.getNodes())); // in parallel we need node type UInt nb_proc = StaticCommunicator::getStaticCommunicator().getNbProc(); if (nb_proc > 1) { registerField("nodes_type", new dumper::NodalField<NodeType>(mesh.getNodesType())); } } /* -------------------------------------------------------------------------- */ void DumperText::registerFilteredMesh( const Mesh & mesh, __attribute__((unused)) const ElementTypeMapArray<UInt> & elements_filter, const Array<UInt> & nodes_filter, __attribute__((unused)) UInt spatial_dimension, __attribute__((unused)) const GhostType & ghost_type, __attribute__((unused)) const ElementKind & element_kind) { registerField("position", new dumper::NodalField<Real, true>( mesh.getNodes(), 0, 0, &nodes_filter)); // in parallel we need node type UInt nb_proc = StaticCommunicator::getStaticCommunicator().getNbProc(); if (nb_proc > 1) { registerField("nodes_type", new dumper::NodalField<NodeType, true>( mesh.getNodesType(), 0, 0, &nodes_filter)); } } /* -------------------------------------------------------------------------- */ void DumperText::setBaseName(const std::string & basename) { AKANTU_DEBUG_IN(); DumperIOHelper::setBaseName(basename); static_cast<iohelper::DumperText *>(this->dumper) ->setDataSubDirectory(this->filename + "-DataFiles"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void DumperText::setPrecision(UInt prec) { AKANTU_DEBUG_IN(); static_cast<iohelper::DumperText *>(this->dumper)->setPrecision(prec); AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu diff --git a/src/io/dumper/dumper_text.hh b/src/io/dumper/dumper_text.hh index cd698f947..8a367d021 100644 --- a/src/io/dumper/dumper_text.hh +++ b/src/io/dumper/dumper_text.hh @@ -1,88 +1,88 @@ /** * @file dumper_text.hh * * @author David Simon Kammer <david.kammer@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief to dump into a text file * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "dumper_iohelper.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_DUMPER_TEXT_HH__ #define __AKANTU_DUMPER_TEXT_HH__ /* -------------------------------------------------------------------------- */ #include <io_helper.hh> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class DumperText : public DumperIOHelper { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: DumperText(const std::string & basename = "dumper_text", iohelper::TextDumpMode mode = iohelper::_tdm_space, bool parallel = true); virtual ~DumperText() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void registerMesh(const Mesh & mesh, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); virtual void registerFilteredMesh(const Mesh & mesh, const ElementTypeMapArray<UInt> & elements_filter, const Array<UInt> & nodes_filter, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); virtual void setBaseName(const std::string & basename); private: void registerNodeTypeField(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: void setPrecision(UInt prec); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DUMPER_TEXT_HH__ */ diff --git a/src/io/dumper/dumper_type_traits.hh b/src/io/dumper/dumper_type_traits.hh index be7ce42ce..d9b1b33ad 100644 --- a/src/io/dumper/dumper_type_traits.hh +++ b/src/io/dumper/dumper_type_traits.hh @@ -1,99 +1,99 @@ /** * @file dumper_type_traits.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * * @date creation: Tue Sep 02 2014 * @date last modification: Mon Sep 21 2015 * * @brief Type traits for field properties * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_DUMPER_TYPE_TRAITS_HH__ #define __AKANTU_DUMPER_TYPE_TRAITS_HH__ /* -------------------------------------------------------------------------- */ #include "element_type_map.hh" #include "element_type_map_filter.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { __BEGIN_AKANTU_DUMPER__ /* -------------------------------------------------------------------------- */ template <class data, class ret, class field> struct TypeTraits { //! the stored data (real, int, uint, ...) typedef data data_type; //! the type returned by the operator * typedef ret return_type; //! the field type (ElementTypeMap or ElementTypeMapFilter) typedef field field_type; //! the type over which we iterate typedef typename field_type::type it_type; //! the type of array (Array<T> or ArrayFilter<T>) typedef typename field_type::array_type array_type; //! the iterator over the array typedef typename array_type::const_vector_iterator array_iterator; }; /* -------------------------------------------------------------------------- */ // specialization for the case in which input and output types are the same template <class T, template <class> class ret, bool filtered> struct SingleType : public TypeTraits<T,ret<T>,ElementTypeMapArray<T> >{ }; /* -------------------------------------------------------------------------- */ // same as before but for filtered data template <class T, template <class> class ret> struct SingleType<T,ret,true> : public TypeTraits<T,ret<T>, ElementTypeMapArrayFilter<T> >{ }; /* -------------------------------------------------------------------------- */ // specialization for the case in which input and output types are different template <class it_type, class data_type, template <class> class ret, bool filtered> struct DualType : public TypeTraits<data_type,ret<data_type>, ElementTypeMapArray<it_type> >{ }; /* -------------------------------------------------------------------------- */ // same as before but for filtered data template <class it_type, class data_type,template <class> class ret> struct DualType<it_type,data_type,ret,true> : public TypeTraits<data_type,ret<data_type>, ElementTypeMapArrayFilter<it_type> >{ }; /* -------------------------------------------------------------------------- */ __END_AKANTU_DUMPER__ -__END_AKANTU__ +} // akantu /* -------------------------------------------------------------------------- */ #endif /* __AKANTU_DUMPER_TYPE_TRAITS_HH__ */ diff --git a/src/io/dumper/dumper_variable.hh b/src/io/dumper/dumper_variable.hh index 0bdda9da1..498ea37c9 100644 --- a/src/io/dumper/dumper_variable.hh +++ b/src/io/dumper/dumper_variable.hh @@ -1,118 +1,118 @@ /** * @file dumper_variable.hh * * @author David Simon Kammer <david.kammer@epfl.ch> * * @date creation: Tue Jun 04 2013 * @date last modification: Sun Oct 19 2014 * * @brief template of variable * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_DUMPER_IOHELPER_TMPL_VARIABLE_HH__ #define __AKANTU_DUMPER_IOHELPER_TMPL_VARIABLE_HH__ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { __BEGIN_AKANTU_DUMPER__ /* -------------------------------------------------------------------------- */ /// Variable interface class VariableBase { public: VariableBase() {}; virtual ~VariableBase() {}; virtual void registerToDumper(const std::string & id, iohelper::Dumper & dumper) = 0; }; /* -------------------------------------------------------------------------- */ template<typename T, bool is_scal = is_scalar<T>::value > class Variable : public VariableBase { public: Variable(const T & t) : vari(t) {} virtual void registerToDumper(const std::string & id, iohelper::Dumper & dumper) { dumper.addVariable(id, *this); } const T & operator[](UInt i) const { return vari[i]; } UInt getDim() { return vari.size(); } iohelper::DataType getDataType() { return iohelper::getDataType<T>(); } protected: const T & vari; }; /* -------------------------------------------------------------------------- */ template<typename T> class Variable<Vector<T>, false> : public VariableBase { public: Variable(const Vector<T> & t) : vari(t) {} virtual void registerToDumper(const std::string & id, iohelper::Dumper & dumper) { dumper.addVariable(id, *this); } const T & operator[](UInt i) const { return vari[i]; } UInt getDim() { return vari.size(); } iohelper::DataType getDataType() { return iohelper::getDataType<T>(); } protected: const Vector<T> & vari; }; /* -------------------------------------------------------------------------- */ template<typename T> class Variable<T, true> : public VariableBase { public: Variable(const T & t) : vari(t) {} virtual void registerToDumper(const std::string & id, iohelper::Dumper & dumper) { dumper.addVariable(id, *this); } const T & operator[](__attribute__((unused)) UInt i) const { return vari; } UInt getDim() { return 1; } iohelper::DataType getDataType() { return iohelper::getDataType<T>(); } protected: const T & vari; }; __END_AKANTU_DUMPER__ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DUMPER_IOHELPER_TMPL_VARIABLE_HH__ */ diff --git a/src/io/mesh_io.cc b/src/io/mesh_io.cc index 9235a8d3b..e4ed84cca 100644 --- a/src/io/mesh_io.cc +++ b/src/io/mesh_io.cc @@ -1,156 +1,156 @@ /** * @file mesh_io.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Mon Jun 01 2015 * * @brief common part for all mesh io classes * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh_io.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ MeshIO::MeshIO() { canReadSurface = false; canReadExtendedData = false; } /* -------------------------------------------------------------------------- */ MeshIO::~MeshIO() {} /* -------------------------------------------------------------------------- */ MeshIO * MeshIO::getMeshIO(const std::string & filename, const MeshIOType & type) { MeshIOType t = type; if (type == _miot_auto) { std::string::size_type idx = filename.rfind('.'); std::string ext; if (idx != std::string::npos) { ext = filename.substr(idx + 1); } if (ext == "msh") { t = _miot_gmsh; } else if (ext == "diana") { t = _miot_diana; } else if (ext == "inp") { t = _miot_abaqus; } else AKANTU_EXCEPTION("Cannot guess the type of file of " << filename << " (ext " << ext << "). " << "Please provide the MeshIOType to the read function"); } switch (t) { case _miot_gmsh: return new MeshIOMSH(); #if defined(AKANTU_STRUCTURAL_MECHANICS) case _miot_gmsh_struct: return new MeshIOMSHStruct(); #endif case _miot_diana: return new MeshIODiana(); case _miot_abaqus: return new MeshIOAbaqus(); default: return NULL; } } /* -------------------------------------------------------------------------- */ void MeshIO::read(const std::string & filename, Mesh & mesh, const MeshIOType & type) { MeshIO * mesh_io = getMeshIO(filename, type); mesh_io->read(filename, mesh); delete mesh_io; } /* -------------------------------------------------------------------------- */ void MeshIO::write(const std::string & filename, Mesh & mesh, const MeshIOType & type) { MeshIO * mesh_io = getMeshIO(filename, type); mesh_io->write(filename, mesh); delete mesh_io; } /* -------------------------------------------------------------------------- */ void MeshIO::constructPhysicalNames(const std::string & tag_name, Mesh & mesh) { if (!phys_name_map.empty()) { for (Mesh::type_iterator type_it = mesh.firstType(); type_it != mesh.lastType(); ++type_it) { Array<std::string> * name_vec = mesh.getDataPointer<std::string>("physical_names", *type_it); const Array<UInt> & tags_vec = mesh.getData<UInt>(tag_name, *type_it); for (UInt i(0); i < tags_vec.getSize(); i++) { std::map<UInt, std::string>::const_iterator map_it = phys_name_map.find(tags_vec(i)); if (map_it == phys_name_map.end()) { std::stringstream sstm; sstm << tags_vec(i); name_vec->operator()(i) = sstm.str(); } else { name_vec->operator()(i) = map_it->second; } } } } } /* -------------------------------------------------------------------------- */ void MeshIO::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; if (phys_name_map.size()) { stream << space << "Physical map:" << std::endl; std::map<UInt, std::string>::const_iterator it = phys_name_map.begin(); std::map<UInt, std::string>::const_iterator end = phys_name_map.end(); for (; it != end; ++it) { stream << space << it->first << ": " << it->second << std::endl; } } } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/io/mesh_io.hh b/src/io/mesh_io.hh index 2184bc2b0..680d7d418 100644 --- a/src/io/mesh_io.hh +++ b/src/io/mesh_io.hh @@ -1,118 +1,118 @@ /** * @file mesh_io.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Mon Jun 01 2015 * * @brief interface of a mesh io class, reader and writer * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_IO_HH__ #define __AKANTU_MESH_IO_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_accessor.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class MeshIO { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshIO(); virtual ~MeshIO(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void read(const std::string & filename, Mesh & mesh, const MeshIOType & type); void write(const std::string & filename, Mesh & mesh, const MeshIOType & type); /// read a mesh from the file virtual void read(__attribute__((unused)) const std::string & filename, __attribute__((unused)) Mesh & mesh) {} /// write a mesh to a file virtual void write(__attribute__((unused)) const std::string & filename, __attribute__((unused)) const Mesh & mesh) {} /// function to request the manual construction of the physical names maps virtual void constructPhysicalNames(const std::string & tag_name, Mesh & mesh); /// method to permit to be printed to a generic stream virtual void printself(std::ostream & stream, int indent = 0) const; /// static contruction of a meshio object static MeshIO * getMeshIO(const std::string & filename, const MeshIOType & type); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: std::map<UInt, std::string> & getPhysicalNameMap() { return phys_name_map; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: bool canReadSurface; bool canReadExtendedData; /// correspondance between a tag and physical names (if applicable) std::map<UInt, std::string> phys_name_map; }; /* -------------------------------------------------------------------------- */ inline std::ostream & operator<<(std::ostream & stream, const MeshIO & _this) { _this.printself(stream); return stream; } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #include "mesh_io_msh.hh" #include "mesh_io_diana.hh" #include "mesh_io_abaqus.hh" #if defined(AKANTU_STRUCTURAL_MECHANICS) #include "mesh_io_msh_struct.hh" #endif #endif /* __AKANTU_MESH_IO_HH__ */ diff --git a/src/io/mesh_io/mesh_io_abaqus.cc b/src/io/mesh_io/mesh_io_abaqus.cc index f5b8105d8..2caf717c8 100644 --- a/src/io/mesh_io/mesh_io_abaqus.cc +++ b/src/io/mesh_io/mesh_io_abaqus.cc @@ -1,483 +1,483 @@ /** * @file mesh_io_abaqus.cc * * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jan 04 2013 * @date last modification: Fri Dec 11 2015 * * @brief read a mesh from an abaqus input file * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ // std library header files #include <fstream> // akantu header files #include "mesh_io_abaqus.hh" #include "mesh.hh" #include "mesh_utils.hh" #include "element_group.hh" #include "node_group.hh" #if defined(__INTEL_COMPILER) //#pragma warning ( disable : 383 ) #elif defined (__clang__) // test clang to be sure that when we test for gnu it is only gnu #elif (defined(__GNUC__) || defined(__GNUG__)) # define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) # if GCC_VERSION > 40600 # pragma GCC diagnostic push # endif # pragma GCC diagnostic ignored "-Wunused-local-typedefs" #endif /* -------------------------------------------------------------------------- */ #include <boost/config/warning_disable.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ MeshIOAbaqus::MeshIOAbaqus() {} /* -------------------------------------------------------------------------- */ MeshIOAbaqus::~MeshIOAbaqus() {} /* -------------------------------------------------------------------------- */ namespace spirit = boost::spirit; namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; namespace lbs = boost::spirit::qi::labels; namespace phx = boost::phoenix; /* -------------------------------------------------------------------------- */ void element_read(Mesh & mesh, const ElementType & type, UInt id, const std::vector<Int> & conn, const std::map<UInt, UInt> & nodes_mapping, std::map<UInt, Element> & elements_mapping) { Vector<UInt> tmp_conn(Mesh::getNbNodesPerElement(type)); AKANTU_DEBUG_ASSERT(conn.size() == tmp_conn.size(), "The nodes in the Abaqus file have too many coordinates" << " for the mesh you try to fill."); mesh.addConnectivityType(type); Array<UInt> & connectivity = mesh.getConnectivity(type); UInt i = 0; for (std::vector<Int>::const_iterator it = conn.begin(); it != conn.end(); ++it) { std::map<UInt, UInt>::const_iterator nit = nodes_mapping.find(*it); AKANTU_DEBUG_ASSERT(nit != nodes_mapping.end(), "There is an unknown node in the connectivity."); tmp_conn[i++] = nit->second; } Element el(type, connectivity.getSize()); elements_mapping[id] = el; connectivity.push_back(tmp_conn); } void node_read(Mesh & mesh, UInt id, const std::vector<Real> & pos, std::map<UInt, UInt> & nodes_mapping) { Vector<Real> tmp_pos(mesh.getSpatialDimension()); UInt i = 0; for (std::vector<Real>::const_iterator it = pos.begin(); it != pos.end() || i < mesh.getSpatialDimension(); ++it) tmp_pos[i++] = *it; nodes_mapping[id] = mesh.getNbNodes(); mesh.getNodes().push_back(tmp_pos); } /* ------------------------------------------------------------------------ */ void add_element_to_group(ElementGroup * el_grp, UInt element, const std::map<UInt, Element> & elements_mapping) { std::map<UInt, Element>::const_iterator eit = elements_mapping.find(element); AKANTU_DEBUG_ASSERT(eit != elements_mapping.end(), "There is an unknown element (" << element << ") in the in the ELSET " << el_grp->getName() << "."); el_grp->add(eit->second, true, false); } ElementGroup * element_group_create(Mesh & mesh, const ID & name) { Mesh::element_group_iterator eg_it = mesh.element_group_find(name); if (eg_it != mesh.element_group_end()) { return eg_it->second; } else { return &mesh.createElementGroup(name, _all_dimensions); } } NodeGroup * node_group_create(Mesh & mesh, const ID & name) { Mesh::node_group_iterator ng_it = mesh.node_group_find(name); if (ng_it != mesh.node_group_end()) { return ng_it->second; } else { return &mesh.createNodeGroup(name, mesh.getSpatialDimension()); } } void add_node_to_group(NodeGroup * node_grp, UInt node, const std::map<UInt, UInt> & nodes_mapping) { std::map<UInt, UInt>::const_iterator nit = nodes_mapping.find(node); AKANTU_DEBUG_ASSERT(nit != nodes_mapping.end(), "There is an unknown node in the in the NSET " << node_grp->getName() << "."); node_grp->add(nit->second, false); } void optimize_group(NodeGroup * grp) { grp->optimize(); } void optimize_element_group(ElementGroup * grp) { grp->optimize(); } /* -------------------------------------------------------------------------- */ template <class Iterator> struct AbaqusSkipper : qi::grammar<Iterator> { AbaqusSkipper() : AbaqusSkipper::base_type(skip, "abaqus_skipper") { /* clang-format off */ skip = (ascii::space - spirit::eol) | "**" >> *(qi::char_ - spirit::eol) >> spirit::eol ; /* clang-format on */ } qi::rule<Iterator> skip; }; /* -------------------------------------------------------------------------- */ template <class Iterator, typename Skipper = AbaqusSkipper<Iterator> > struct AbaqusMeshGrammar : qi::grammar<Iterator, void(), Skipper> { public: AbaqusMeshGrammar(Mesh & mesh) : AbaqusMeshGrammar::base_type(start, "abaqus_mesh_reader"), mesh(mesh) { /* clang-format off */ start = *( (qi::char_('*') > ( (qi::no_case[ qi::lit("node output") ] > any_section) | (qi::no_case[ qi::lit("element output") ] > any_section) | (qi::no_case[ qi::lit("node") ] > nodes) | (qi::no_case[ qi::lit("element") ] > elements) | (qi::no_case[ qi::lit("heading") ] > header) | (qi::no_case[ qi::lit("elset") ] > elements_set) | (qi::no_case[ qi::lit("nset") ] > nodes_set) | (qi::no_case[ qi::lit("material") ] > material) | (keyword > any_section) ) ) | spirit::eol ) ; header = spirit::eol > *any_line ; nodes = *(qi::char_(',') >> option) >> spirit::eol >> *( (qi::int_ > node_position) [ phx::bind(&node_read, phx::ref(mesh), lbs::_1, lbs::_2, phx::ref(abaqus_nodes_to_akantu)) ] >> spirit::eol ) ; elements = ( ( qi::char_(',') >> qi::no_case[qi::lit("type")] >> '=' >> abaqus_element_type [ lbs::_a = lbs::_1 ] ) ^ *(qi::char_(',') >> option) ) >> spirit::eol >> *( (qi::int_ > connectivity) [ phx::bind(&element_read, phx::ref(mesh), lbs::_a, lbs::_1, lbs::_2, phx::cref(abaqus_nodes_to_akantu), phx::ref(abaqus_elements_to_akantu)) ] >> spirit::eol ) ; elements_set = ( ( ( qi::char_(',') >> qi::no_case[ qi::lit("elset") ] >> '=' >> value [ lbs::_a = phx::bind<ElementGroup *>(&element_group_create, phx::ref(mesh), lbs::_1) ] ) ^ *(qi::char_(',') >> option) ) >> spirit::eol >> qi::skip (qi::char_(',') | qi::space) [ +(qi::int_ [ phx::bind(&add_element_to_group, lbs::_a, lbs::_1, phx::cref(abaqus_elements_to_akantu) ) ] ) ] ) [ phx::bind(&optimize_element_group, lbs::_a) ] ; nodes_set = ( ( ( qi::char_(',') >> qi::no_case[ qi::lit("nset") ] >> '=' >> value [ lbs::_a = phx::bind<NodeGroup *>(&node_group_create, phx::ref(mesh), lbs::_1) ] ) ^ *(qi::char_(',') >> option) ) >> spirit::eol >> qi::skip (qi::char_(',') | qi::space) [ +(qi::int_ [ phx::bind(&add_node_to_group, lbs::_a, lbs::_1, phx::cref(abaqus_nodes_to_akantu) ) ] ) ] ) [ phx::bind(&optimize_group, lbs::_a) ] ; material = ( ( qi::char_(',') >> qi::no_case[ qi::lit("name") ] >> '=' >> value [ phx::push_back(phx::ref(material_names), lbs::_1) ] ) ^ *(qi::char_(',') >> option) ) >> spirit::eol; ; node_position = +(qi::char_(',') > real [ phx::push_back(lbs::_val, lbs::_1) ]) ; connectivity = +(qi::char_(',') > qi::int_ [ phx::push_back(lbs::_val, lbs::_1) ]) ; any_section = *(qi::char_(',') >> option) > spirit::eol > *any_line ; any_line = *(qi::char_ - spirit::eol - qi::char_('*')) >> spirit::eol ; keyword = qi::lexeme[ +(qi::char_ - (qi::char_('*') | spirit::eol)) ] ; option = key > -( '=' >> value ); key = qi::char_("a-zA-Z_") >> *(qi::char_("a-zA-Z_0-9") | qi::char_('-')) ; value = key.alias() ; BOOST_SPIRIT_DEBUG_NODE(start); abaqus_element_type.add #if defined(AKANTU_STRUCTURAL_MECHANICS) ("BE21" , _bernoulli_beam_2) ("BE31" , _bernoulli_beam_3) #endif ("T3D2" , _segment_2) // Gmsh generates this elements ("T3D3" , _segment_3) // Gmsh generates this elements ("CPE3" , _triangle_3) ("CPS3" , _triangle_3) ("DC2D3" , _triangle_3) ("CPE6" , _triangle_6) ("CPS6" , _triangle_6) ("DC2D6" , _triangle_6) ("CPE4" , _quadrangle_4) ("CPS4" , _quadrangle_4) ("DC2D4" , _quadrangle_4) ("CPE8" , _quadrangle_8) ("CPS8" , _quadrangle_8) ("DC2D8" , _quadrangle_8) ("C3D4" , _tetrahedron_4) ("DC3D4" , _tetrahedron_4) ("C3D8" , _hexahedron_8) ("C3D8R" , _hexahedron_8) ("DC3D8" , _hexahedron_8) ("C3D10" , _tetrahedron_10) ("DC3D10", _tetrahedron_10); #if !defined(AKANTU_NDEBUG) && defined(AKANTU_CORE_CXX_11) qi::on_error<qi::fail>(start, error_handler(lbs::_4, lbs::_3, lbs::_2)); #endif start .name("abaqus-start-rule"); connectivity .name("abaqus-connectivity"); node_position .name("abaqus-nodes-position"); nodes .name("abaqus-nodes"); any_section .name("abaqus-any_section"); header .name("abaqus-header"); material .name("abaqus-material"); elements .name("abaqus-elements"); elements_set .name("abaqus-elements-set"); nodes_set .name("abaqus-nodes-set"); key .name("abaqus-key"); value .name("abaqus-value"); option .name("abaqus-option"); keyword .name("abaqus-keyword"); any_line .name("abaqus-any-line"); abaqus_element_type.name("abaqus-element-type"); /* clang-format on */ } public: AKANTU_GET_MACRO(MaterialNames, material_names, const std::vector<std::string> &); /* ------------------------------------------------------------------------ */ /* Rules */ /* ------------------------------------------------------------------------ */ private: qi::rule<Iterator, void(), Skipper> start; qi::rule<Iterator, std::vector<int>(), Skipper> connectivity; qi::rule<Iterator, std::vector<Real>(), Skipper> node_position; qi::rule<Iterator, void(), Skipper> nodes, any_section, header, material; qi::rule<Iterator, void(), qi::locals<ElementType>, Skipper> elements; qi::rule<Iterator, void(), qi::locals<ElementGroup *>, Skipper> elements_set; qi::rule<Iterator, void(), qi::locals<NodeGroup *>, Skipper> nodes_set; qi::rule<Iterator, std::string(), Skipper> key, value, option, keyword, any_line; qi::real_parser<Real, qi::real_policies<Real> > real; qi::symbols<char, ElementType> abaqus_element_type; /* ------------------------------------------------------------------------ */ /* Mambers */ /* ------------------------------------------------------------------------ */ private: /// reference to the mesh to read Mesh & mesh; /// correspondance between the numbering of nodes in the abaqus file and in /// the akantu mesh std::map<UInt, UInt> abaqus_nodes_to_akantu; /// correspondance between the element number in the abaqus file and the /// Element in the akantu mesh std::map<UInt, Element> abaqus_elements_to_akantu; /// list of the material names std::vector<std::string> material_names; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void MeshIOAbaqus::read(const std::string & filename, Mesh & mesh) { namespace spirit = boost::spirit; namespace qi = boost::spirit::qi; namespace lbs = boost::spirit::qi::labels; namespace ascii = boost::spirit::ascii; namespace phx = boost::phoenix; std::ifstream infile; infile.open(filename.c_str()); if (!infile.good()) { AKANTU_DEBUG_ERROR("Cannot open file " << filename); } std::string storage; // We will read the contents here. infile.unsetf(std::ios::skipws); // No white space skipping! std::copy(std::istream_iterator<char>(infile), std::istream_iterator<char>(), std::back_inserter(storage)); typedef std::string::const_iterator iterator_t; typedef AbaqusSkipper<iterator_t> skipper; typedef AbaqusMeshGrammar<iterator_t, skipper> grammar; grammar g(mesh); skipper ws; iterator_t iter = storage.begin(); iterator_t end = storage.end(); qi::phrase_parse(iter, end, g, ws); std::vector<std::string>::const_iterator mnit = g.getMaterialNames().begin(); std::vector<std::string>::const_iterator mnend = g.getMaterialNames().end(); MeshAccessor mesh_accessor(mesh); for (; mnit != mnend; ++mnit) { Mesh::element_group_iterator eg_it = mesh.element_group_find(*mnit); ElementGroup & eg = *eg_it->second; if (eg_it != mesh.element_group_end()) { ElementGroup::type_iterator tit = eg.firstType(); ElementGroup::type_iterator tend = eg.lastType(); for (; tit != tend; ++tit) { Array<std::string> & abaqus_material = mesh_accessor.getData<std::string>("abaqus_material", *tit); ElementGroup::const_element_iterator eit = eg.element_begin(*tit); ElementGroup::const_element_iterator eend = eg.element_end(*tit); for (; eit != eend; ++eit) { abaqus_material(*eit) = *mnit; } } } } mesh_accessor.setNbGlobalNodes(mesh.getNodes().getSize()); MeshUtils::fillElementToSubElementsData(mesh); } -__END_AKANTU__ +} // akantu diff --git a/src/io/mesh_io/mesh_io_abaqus.hh b/src/io/mesh_io/mesh_io_abaqus.hh index 9500115fc..877d87efc 100644 --- a/src/io/mesh_io/mesh_io_abaqus.hh +++ b/src/io/mesh_io/mesh_io_abaqus.hh @@ -1,60 +1,60 @@ /** * @file mesh_io_abaqus.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sun Sep 26 2010 * @date last modification: Tue Jun 30 2015 * * @brief read a mesh from an abaqus input file * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "mesh_io.hh" #include "mesh_accessor.hh" #ifndef __AKANTU_MESH_IO_ABAQUS_HH__ #define __AKANTU_MESH_IO_ABAQUS_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ class MeshIOAbaqus : public MeshIO { public: MeshIOAbaqus(); virtual ~MeshIOAbaqus(); /// read a mesh from the file virtual void read(const std::string & filename, Mesh & mesh); /// write a mesh to a file // virtual void write(const std::string & filename, const Mesh & mesh); private: /// correspondence between msh element types and akantu element types std::map<std::string, ElementType> _abaqus_to_akantu_element_types; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MESH_IO_ABAQUS_HH__ */ diff --git a/src/io/mesh_io/mesh_io_diana.cc b/src/io/mesh_io/mesh_io_diana.cc index e94065209..2014b6b92 100644 --- a/src/io/mesh_io/mesh_io_diana.cc +++ b/src/io/mesh_io/mesh_io_diana.cc @@ -1,587 +1,587 @@ /** * @file mesh_io_diana.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Alodie Schneuwly <alodie.schneuwly@epfl.ch> * * @date creation: Sat Mar 26 2011 * @date last modification: Thu Jan 21 2016 * * @brief handles diana meshes * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include <fstream> #include <iostream> /* -------------------------------------------------------------------------- */ #include "mesh_io_diana.hh" #include "mesh_utils.hh" #include "element_group.hh" /* -------------------------------------------------------------------------- */ #include <string.h> /* -------------------------------------------------------------------------- */ #include <stdio.h> -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* Methods Implentations */ /* -------------------------------------------------------------------------- */ MeshIODiana::MeshIODiana() { canReadSurface = true; canReadExtendedData = true; _diana_to_akantu_element_types["T9TM"] = _triangle_3; _diana_to_akantu_element_types["CT6CM"] = _triangle_6; _diana_to_akantu_element_types["Q12TM"] = _quadrangle_4; _diana_to_akantu_element_types["CQ8CM"] = _quadrangle_8; _diana_to_akantu_element_types["TP18L"] = _pentahedron_6; _diana_to_akantu_element_types["CTP45"] = _pentahedron_15; _diana_to_akantu_element_types["TE12L"] = _tetrahedron_4; _diana_to_akantu_element_types["HX24L"] = _hexahedron_8; _diana_to_akantu_element_types["CHX60"] = _hexahedron_20; _diana_to_akantu_mat_prop["YOUNG"] = "E"; _diana_to_akantu_mat_prop["DENSIT"] = "rho"; _diana_to_akantu_mat_prop["POISON"] = "nu"; std::map<std::string, ElementType>::iterator it; for (it = _diana_to_akantu_element_types.begin(); it != _diana_to_akantu_element_types.end(); ++it) { UInt nb_nodes = Mesh::getNbNodesPerElement(it->second); UInt * tmp = new UInt[nb_nodes]; for (UInt i = 0; i < nb_nodes; ++i) { tmp[i] = i; } switch (it->second) { case _tetrahedron_10: tmp[8] = 9; tmp[9] = 8; break; case _pentahedron_15: tmp[0] = 2; tmp[1] = 8; tmp[2] = 0; tmp[3] = 6; tmp[4] = 1; tmp[5] = 7; tmp[6] = 11; tmp[7] = 9; tmp[8] = 10; tmp[9] = 5; tmp[10] = 14; tmp[11] = 3; tmp[12] = 12; tmp[13] = 4; tmp[14] = 13; break; case _hexahedron_20: tmp[0] = 5; tmp[1] = 16; tmp[2] = 4; tmp[3] = 19; tmp[4] = 7; tmp[5] = 18; tmp[6] = 6; tmp[7] = 17; tmp[8] = 13; tmp[9] = 12; tmp[10] = 15; tmp[11] = 14; tmp[12] = 1; tmp[13] = 8; tmp[14] = 0; tmp[15] = 11; tmp[16] = 3; tmp[17] = 10; tmp[18] = 2; tmp[19] = 9; break; default: // nothing to change break; } _read_order[it->second] = tmp; } } /* -------------------------------------------------------------------------- */ MeshIODiana::~MeshIODiana() {} /* -------------------------------------------------------------------------- */ 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(); MeshAccessor mesh_accessor(mesh); std::ifstream infile; infile.open(filename.c_str()); std::string line; UInt first_node_number = std::numeric_limits<UInt>::max(); diana_element_number_to_elements.clear(); 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, first_node_number); } /// read the material properties and write a .dat file if (line == "'MATERIALS'") { line = readMaterial(infile, filename); } /// read the material properties and write a .dat file if (line == "'GROUPS'") { line = readGroups(infile, mesh, first_node_number); } } infile.close(); mesh_accessor.setNbGlobalNodes(mesh.getNbNodes()); MeshUtils::fillElementToSubElementsData(mesh); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshIODiana::write(__attribute__((unused)) const std::string & filename, __attribute__((unused)) const Mesh & mesh) { AKANTU_DEBUG_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readCoordinates(std::ifstream & infile, Mesh & mesh, UInt & first_node_number) { AKANTU_DEBUG_IN(); MeshAccessor mesh_accessor(mesh); Array<Real> & nodes = mesh_accessor.getNodes(); std::string line; UInt index; Vector<Real> coord(3); do { my_getline(infile, line); if ("'ELEMENTS'" == line) break; std::stringstream sstr_node(line); sstr_node >> index >> coord(0) >> coord(1) >> coord(2); first_node_number = first_node_number < index ? first_node_number : index; nodes.push_back(coord); } while (true); AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ UInt MeshIODiana::readInterval(std::stringstream & line, std::set<UInt> & interval) { UInt first; line >> first; if (line.fail()) { return 0; } interval.insert(first); UInt second; int 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, 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; my_getline(infile, line); } if (line == "ELEMEN") { reading_nodes_group = false; my_getline(infile, line); } std::stringstream * str = new std::stringstream(line); UInt id; std::string name; char c; *str >> id >> name >> c; Array<UInt> * list_ids = new Array<UInt>(0, 1, name); UInt s = 1; bool end = false; while (!end) { while (!str->eof() && s != 0) { std::set<UInt> interval; s = readInterval(*str, interval); std::set<UInt>::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) { NodeGroup & ng = mesh.createNodeGroup(name); for (UInt i = 0; i < list_ids->getSize(); ++i) { UInt node = (*list_ids)(i) - first_node_number; ng.add(node, false); } delete list_ids; } else { ElementGroup & eg = mesh.createElementGroup(name); for (UInt i = 0; i < list_ids->getSize(); ++i) { Element & elem = diana_element_number_to_elements[ (*list_ids)(i)]; if (elem.type != _not_defined) eg.add(elem, false, false); } eg.optimize(); delete list_ids; } my_getline(infile, line); } AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readElements(std::ifstream & infile, Mesh & mesh, UInt first_node_number) { AKANTU_DEBUG_IN(); std::string line; my_getline(infile, line); if ("CONNECTIVITY" == line) { line = readConnectivity(infile, mesh, first_node_number); } /// read the line corresponding to the materials if ("MATERIALS" == line) { line = readMaterialElement(infile, mesh); } AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readConnectivity(std::ifstream & infile, Mesh & mesh, UInt first_node_number) { AKANTU_DEBUG_IN(); MeshAccessor mesh_accessor(mesh); Int index; std::string lline; std::string diana_type; ElementType akantu_type, akantu_type_old = _not_defined; Array<UInt> * connectivity = NULL; UInt node_per_element = 0; Element elem; UInt * read_order = NULL; while (1) { my_getline(infile, lline); // std::cerr << lline << std::endl; std::stringstream sstr_elem(lline); if (lline == "MATERIALS") break; /// traiter les coordonnees sstr_elem >> index; sstr_elem >> diana_type; akantu_type = _diana_to_akantu_element_types[diana_type]; if (akantu_type == _not_defined) continue; if (akantu_type != akantu_type_old) { connectivity = &(mesh_accessor.getConnectivity(akantu_type)); node_per_element = connectivity->getNbComponent(); akantu_type_old = akantu_type; read_order = _read_order[akantu_type]; } Vector<UInt> local_connect(node_per_element); // used if element is written on two lines UInt j_last = 0; for (UInt j = 0; j < node_per_element; ++j) { UInt node_index; sstr_elem >> node_index; // check s'il y a pas plus rien après un certain point if (sstr_elem.fail()) { sstr_elem.clear(); sstr_elem.ignore(); break; } node_index -= first_node_number; local_connect(read_order[j]) = node_index; j_last = j; } // check if element is written in two lines if (j_last != (node_per_element - 1)) { // if this is the case, read on more line my_getline(infile, lline); std::stringstream sstr_elem(lline); for (UInt j = (j_last + 1); j < node_per_element; ++j) { UInt node_index; sstr_elem >> node_index; node_index -= first_node_number; local_connect(read_order[j]) = node_index; } } connectivity->push_back(local_connect); elem.type = akantu_type; elem.element = connectivity->getSize() - 1; diana_element_number_to_elements[index] = elem; akantu_number_to_diana_number[elem] = index; } AKANTU_DEBUG_OUT(); return lline; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readMaterialElement(std::ifstream & infile, Mesh & mesh) { AKANTU_DEBUG_IN(); std::string line; std::stringstream sstr_tag_name; sstr_tag_name << "tag_" << 0; Mesh::type_iterator it = mesh.firstType(); Mesh::type_iterator end = mesh.lastType(); for (; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it); mesh.getDataPointer<UInt>("material", *it, _not_ghost, 1) ->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()); AKANTU_DEBUG_WARNING("reading line " << line); Array<UInt> temp_id(0, 2); UInt mat; while (true) { std::stringstream sstr_intervals_elements(line); Vector<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.storage(); for (UInt i = 0; i < temp_id.getSize(); ++i) for (UInt j = temp_id(i, 0); j <= temp_id(i, 1); ++j) { Element & element = diana_element_number_to_elements[j]; if (element.type == _not_defined) continue; UInt elem = element.element; ElementType type = element.type; Array<UInt> & data = *(mesh.getDataPointer<UInt>("material", type, _not_ghost)); data(elem) = mat; } my_getline(infile, line); } AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readMaterial(std::ifstream & infile, 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; UInt mat_id = 0; typedef std::map<std::string, Real> MatProp; MatProp mat_prop; do { my_getline(infile, line); std::stringstream sstr_material(line); if (("'GROUPS'" == line) || ("'END'" == line)) { if (!mat_prop.empty()) { material_file << "material elastic [" << std::endl; material_file << "\tname = material" << ++mat_id << std::endl; for (MatProp::iterator it = mat_prop.begin(); it != mat_prop.end(); ++it) material_file << "\t" << it->first << " = " << it->second << std::endl; material_file << "]" << std::endl; mat_prop.clear(); } end = true; } else { /// traiter les caractéristiques des matériaux sstr_material >> mat_index; if (!sstr_material.fail()) { if (!first_mat) { if (!mat_prop.empty()) { material_file << "material elastic [" << std::endl; material_file << "\tname = material" << ++mat_id << std::endl; for (MatProp::iterator it = mat_prop.begin(); it != mat_prop.end(); ++it) material_file << "\t" << it->first << " = " << it->second << std::endl; material_file << "]" << std::endl; mat_prop.clear(); } } first_mat = false; } else { sstr_material.clear(); } std::string prop_name; sstr_material >> prop_name; std::map<std::string, std::string>::iterator it; it = _diana_to_akantu_mat_prop.find(prop_name); if (it != _diana_to_akantu_mat_prop.end()) { Real value; sstr_material >> value; mat_prop[it->second] = value; } else { AKANTU_DEBUG_INFO("In material reader, property " << prop_name << "not recognized"); } } } while (!end); AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/io/mesh_io/mesh_io_diana.hh b/src/io/mesh_io/mesh_io_diana.hh index 737c4de68..7ddcbed5c 100644 --- a/src/io/mesh_io/mesh_io_diana.hh +++ b/src/io/mesh_io/mesh_io_diana.hh @@ -1,107 +1,107 @@ /** * @file mesh_io_diana.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Alodie Schneuwly <alodie.schneuwly@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Nov 19 2015 * * @brief diana mesh reader description * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_IO_DIANA_HH__ #define __AKANTU_MESH_IO_DIANA_HH__ /* -------------------------------------------------------------------------- */ #include "mesh_io.hh" /* -------------------------------------------------------------------------- */ #include <vector> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class MeshIODiana : public MeshIO { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshIODiana(); virtual ~MeshIODiana(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// read a mesh from the file virtual void read(const std::string & filename, Mesh & mesh); /// write a mesh to a file virtual void write(const std::string & filename, const Mesh & mesh); private: std::string readCoordinates(std::ifstream & infile, Mesh & mesh, UInt & first_node_number); std::string readElements(std::ifstream & infile, Mesh & mesh, UInt first_node_number); std::string readGroups(std::ifstream & infile, Mesh & mesh, UInt first_node_number); std::string readConnectivity(std::ifstream & infile, Mesh & mesh, UInt first_node_number); std::string readMaterialElement(std::ifstream & infile, Mesh & mesh); std::string readMaterial(std::ifstream & infile, const std::string & filename); UInt readInterval(std::stringstream & line, std::set<UInt> & interval); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: std::map<std::string, ElementType> _diana_to_akantu_element_types; std::map<std::string, std::string> _diana_to_akantu_mat_prop; /// order in witch element as to be read, akantu_node_order = _read_order[diana_node_order] std::map<ElementType, UInt *> _read_order; std::map<UInt, Element> diana_element_number_to_elements; std::map<Element, UInt> akantu_number_to_diana_number; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MESH_IO_DIANA_HH__ */ diff --git a/src/io/mesh_io/mesh_io_msh.cc b/src/io/mesh_io/mesh_io_msh.cc index cd58e9614..44990b5b2 100644 --- a/src/io/mesh_io/mesh_io_msh.cc +++ b/src/io/mesh_io/mesh_io_msh.cc @@ -1,981 +1,981 @@ /** * @file mesh_io_msh.cc * * @author Dana Christen <dana.christen@gmail.com> * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Jan 21 2016 * * @brief Read/Write for MSH files generated by gmsh * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* ----------------------------------------------------------------------------- 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 <fstream> /* -------------------------------------------------------------------------- */ #include "mesh_io.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ // The boost spirit is a work on the way it does not compile so I kept the // current code. The current code does not handle files generated on Windows // <CRLF> // #include <boost/config/warning_disable.hpp> // #include <boost/spirit/include/qi.hpp> // #include <boost/spirit/include/phoenix_core.hpp> // #include <boost/spirit/include/phoenix_fusion.hpp> // #include <boost/spirit/include/phoenix_object.hpp> // #include <boost/spirit/include/phoenix_container.hpp> // #include <boost/spirit/include/phoenix_operator.hpp> // #include <boost/spirit/include/phoenix_bind.hpp> // #include <boost/spirit/include/phoenix_stl.hpp> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* Methods Implentations */ /* -------------------------------------------------------------------------- */ MeshIOMSH::MeshIOMSH() { canReadSurface = true; canReadExtendedData = true; _msh_nodes_per_elem[_msh_not_defined] = 0; _msh_nodes_per_elem[_msh_segment_2] = 2; _msh_nodes_per_elem[_msh_triangle_3] = 3; _msh_nodes_per_elem[_msh_quadrangle_4] = 4; _msh_nodes_per_elem[_msh_tetrahedron_4] = 4; _msh_nodes_per_elem[_msh_hexahedron_8] = 8; _msh_nodes_per_elem[_msh_prism_1] = 6; _msh_nodes_per_elem[_msh_pyramid_1] = 1; _msh_nodes_per_elem[_msh_segment_3] = 3; _msh_nodes_per_elem[_msh_triangle_6] = 6; _msh_nodes_per_elem[_msh_quadrangle_9] = 9; _msh_nodes_per_elem[_msh_tetrahedron_10] = 10; _msh_nodes_per_elem[_msh_hexahedron_27] = 27; _msh_nodes_per_elem[_msh_hexahedron_20] = 20; _msh_nodes_per_elem[_msh_prism_18] = 18; _msh_nodes_per_elem[_msh_prism_15] = 15; _msh_nodes_per_elem[_msh_pyramid_14] = 14; _msh_nodes_per_elem[_msh_point] = 1; _msh_nodes_per_elem[_msh_quadrangle_8] = 8; _msh_to_akantu_element_types[_msh_not_defined] = _not_defined; _msh_to_akantu_element_types[_msh_segment_2] = _segment_2; _msh_to_akantu_element_types[_msh_triangle_3] = _triangle_3; _msh_to_akantu_element_types[_msh_quadrangle_4] = _quadrangle_4; _msh_to_akantu_element_types[_msh_tetrahedron_4] = _tetrahedron_4; _msh_to_akantu_element_types[_msh_hexahedron_8] = _hexahedron_8; _msh_to_akantu_element_types[_msh_prism_1] = _pentahedron_6; _msh_to_akantu_element_types[_msh_pyramid_1] = _not_defined; _msh_to_akantu_element_types[_msh_segment_3] = _segment_3; _msh_to_akantu_element_types[_msh_triangle_6] = _triangle_6; _msh_to_akantu_element_types[_msh_quadrangle_9] = _not_defined; _msh_to_akantu_element_types[_msh_tetrahedron_10] = _tetrahedron_10; _msh_to_akantu_element_types[_msh_hexahedron_27] = _not_defined; _msh_to_akantu_element_types[_msh_hexahedron_20] = _hexahedron_20; _msh_to_akantu_element_types[_msh_prism_18] = _not_defined; _msh_to_akantu_element_types[_msh_prism_15] = _pentahedron_15; _msh_to_akantu_element_types[_msh_pyramid_14] = _not_defined; _msh_to_akantu_element_types[_msh_point] = _point_1; _msh_to_akantu_element_types[_msh_quadrangle_8] = _quadrangle_8; _akantu_to_msh_element_types[_not_defined] = _msh_not_defined; _akantu_to_msh_element_types[_segment_2] = _msh_segment_2; _akantu_to_msh_element_types[_segment_3] = _msh_segment_3; _akantu_to_msh_element_types[_triangle_3] = _msh_triangle_3; _akantu_to_msh_element_types[_triangle_6] = _msh_triangle_6; _akantu_to_msh_element_types[_tetrahedron_4] = _msh_tetrahedron_4; _akantu_to_msh_element_types[_tetrahedron_10] = _msh_tetrahedron_10; _akantu_to_msh_element_types[_quadrangle_4] = _msh_quadrangle_4; _akantu_to_msh_element_types[_quadrangle_8] = _msh_quadrangle_8; _akantu_to_msh_element_types[_hexahedron_8] = _msh_hexahedron_8; _akantu_to_msh_element_types[_hexahedron_20] = _msh_hexahedron_20; _akantu_to_msh_element_types[_pentahedron_6] = _msh_prism_1; _akantu_to_msh_element_types[_pentahedron_15] = _msh_prism_15; _akantu_to_msh_element_types[_point_1] = _msh_point; #if defined(AKANTU_STRUCTURAL_MECHANICS) _akantu_to_msh_element_types[_bernoulli_beam_2] = _msh_segment_2; _akantu_to_msh_element_types[_bernoulli_beam_3] = _msh_segment_2; _akantu_to_msh_element_types[_kirchhoff_shell] = _msh_triangle_3; #endif std::map<ElementType, MSHElementType>::iterator it; for (it = _akantu_to_msh_element_types.begin(); it != _akantu_to_msh_element_types.end(); ++it) { UInt nb_nodes = _msh_nodes_per_elem[it->second]; std::vector<UInt> tmp(nb_nodes); for (UInt i = 0; i < nb_nodes; ++i) { tmp[i] = i; } switch (it->first) { case _tetrahedron_10: tmp[8] = 9; tmp[9] = 8; break; case _pentahedron_6: tmp[0] = 2; tmp[1] = 0; tmp[2] = 1; tmp[3] = 5; tmp[4] = 3; tmp[5] = 4; break; case _pentahedron_15: tmp[0] = 2; tmp[1] = 0; tmp[2] = 1; tmp[3] = 5; tmp[4] = 3; tmp[5] = 4; tmp[6] = 8; tmp[8] = 11; tmp[9] = 6; tmp[10] = 9; tmp[11] = 10; tmp[12] = 14; tmp[14] = 12; break; case _hexahedron_20: tmp[9] = 11; tmp[10] = 12; tmp[11] = 9; tmp[12] = 13; tmp[13] = 10; tmp[17] = 19; tmp[18] = 17; tmp[19] = 18; break; default: // nothing to change break; } _read_order[it->first] = tmp; } } /* -------------------------------------------------------------------------- */ MeshIOMSH::~MeshIOMSH() {} /* -------------------------------------------------------------------------- */ /* Spirit stuff */ /* -------------------------------------------------------------------------- */ // namespace _parser { // namespace spirit = ::boost::spirit; // namespace qi = ::boost::spirit::qi; // namespace ascii = ::boost::spirit::ascii; // namespace lbs = ::boost::spirit::qi::labels; // namespace phx = ::boost::phoenix; // /* ------------------------------------------------------------------------ // */ // /* Lazy functors */ // /* ------------------------------------------------------------------------ // */ // struct _Element { // int index; // std::vector<int> tags; // std::vector<int> connectivity; // ElementType type; // }; // /* ------------------------------------------------------------------------ // */ // struct lazy_get_nb_nodes_ { // template <class elem_type> struct result { typedef int type; }; // template <class elem_type> bool operator()(elem_type et) { // return MeshIOMSH::_msh_nodes_per_elem[et]; // } // }; // /* ------------------------------------------------------------------------ // */ // struct lazy_element_ { // template <class id_t, class tags_t, class elem_type, class conn_t> // struct result { // typedef _Element type; // }; // template <class id_t, class tags_t, class elem_type, class conn_t> // _Element operator()(id_t id, const elem_type & et, const tags_t & t, // const conn_t & c) { // _Element tmp_el; // tmp_el.index = id; // tmp_el.tags = t; // tmp_el.connectivity = c; // tmp_el.type = et; // return tmp_el; // } // }; // /* ------------------------------------------------------------------------ // */ // struct lazy_check_value_ { // template <class T> struct result { typedef void type; }; // template <class T> void operator()(T v1, T v2) { // if (v1 != v2) { // AKANTU_EXCEPTION("The msh parser expected a " // << v2 << " in the header bug got a " << v1); // } // } // }; // /* ------------------------------------------------------------------------ // */ // struct lazy_node_read_ { // template <class Mesh, class ID, class V, class size, class Map> // struct result { // typedef bool type; // }; // template <class Mesh, class ID, class V, class size, class Map> // bool operator()(Mesh & mesh, const ID & id, const V & pos, size max, // Map & nodes_mapping) const { // Vector<Real> tmp_pos(mesh.getSpatialDimension()); // UInt i = 0; // for (typename V::const_iterator it = pos.begin(); // it != pos.end() || i < mesh.getSpatialDimension(); ++it) // tmp_pos[i++] = *it; // nodes_mapping[id] = mesh.getNbNodes(); // mesh.getNodes().push_back(tmp_pos); // return (mesh.getNbNodes() < UInt(max)); // } // }; // /* ------------------------------------------------------------------------ // */ // struct lazy_element_read_ { // template <class Mesh, class EL, class size, class NodeMap, class ElemMap> // struct result { // typedef bool type; // }; // template <class Mesh, class EL, class size, class NodeMap, class ElemMap> // bool operator()(Mesh & mesh, const EL & element, size max, // const NodeMap & nodes_mapping, // ElemMap & elements_mapping) const { // Vector<UInt> tmp_conn(Mesh::getNbNodesPerElement(element.type)); // AKANTU_DEBUG_ASSERT(element.connectivity.size() == tmp_conn.size(), // "The element " // << element.index // << "in the MSH file has too many nodes."); // mesh.addConnectivityType(element.type); // Array<UInt> & connectivity = mesh.getConnectivity(element.type); // UInt i = 0; // for (std::vector<int>::const_iterator it = // element.connectivity.begin(); // it != element.connectivity.end(); ++it) { // typename NodeMap::const_iterator nit = nodes_mapping.find(*it); // AKANTU_DEBUG_ASSERT(nit != nodes_mapping.end(), // "There is an unknown node in the connectivity."); // tmp_conn[i++] = nit->second; // } // ::akantu::Element el(element.type, connectivity.getSize()); // elements_mapping[element.index] = el; // connectivity.push_back(tmp_conn); // for (UInt i = 0; i < element.tags.size(); ++i) { // std::stringstream tag_sstr; // tag_sstr << "tag_" << i; // Array<UInt> * data = // mesh.template getDataPointer<UInt>(tag_sstr.str(), element.type, // _not_ghost); // data->push_back(element.tags[i]); // } // return (mesh.getNbElement() < UInt(max)); // } // }; // /* ------------------------------------------------------------------------ // */ // template <class Iterator, typename Skipper = ascii::space_type> // struct MshMeshGrammar : qi::grammar<Iterator, void(), Skipper> { // public: // MshMeshGrammar(Mesh & mesh) // : MshMeshGrammar::base_type(start, "msh_mesh_reader"), mesh(mesh) { // phx::function<lazy_element_> lazy_element; // phx::function<lazy_get_nb_nodes_> lazy_get_nb_nodes; // phx::function<lazy_check_value_> lazy_check_value; // phx::function<lazy_node_read_> lazy_node_read; // phx::function<lazy_element_read_> lazy_element_read; // clang-format off // start // = *( known_section | unknown_section // ) // ; // known_section // = qi::char_("$") // >> sections [ lbs::_a = lbs::_1 ] // >> qi::lazy(*lbs::_a) // >> qi::lit("$End") // //>> qi::lit(phx::ref(lbs::_a)) // ; // unknown_section // = qi::char_("$") // >> qi::char_("") [ lbs::_a = lbs::_1 ] // >> ignore_section // >> qi::lit("$End") // >> qi::lit(phx::val(lbs::_a)) // ; // mesh_format // version followed by 0 or 1 for ascii or binary // = version >> ( // ( qi::char_("0") // >> qi::int_ [ lazy_check_value(lbs::_1, 8) ] // ) // | ( qi::char_("1") // >> qi::int_ [ lazy_check_value(lbs::_1, 8) ] // >> qi::dword [ lazy_check_value(lbs::_1, 1) ] // ) // ) // ; // nodes // = nodes_ // ; // nodes_ // = qi::int_ [ lbs::_a = lbs::_1 ] // > *( // ( qi::int_ >> position ) [ lazy_node_read(phx::ref(mesh), // lbs::_1, // phx::cref(lbs::_2), // lbs::_a, // phx::ref(this->msh_nodes_to_akantu)) ] // ) // ; // element // = elements_ // ; // elements_ // = qi::int_ [ lbs::_a = lbs::_1 ] // > qi::repeat(phx::ref(lbs::_a))[ element [ lazy_element_read(phx::ref(mesh), // lbs::_1, // phx::cref(lbs::_a), // phx::cref(this->msh_nodes_to_akantu), // phx::ref(this->msh_elemt_to_akantu)) ]] // ; // ignore_section // = *(qi::char_ - qi::char_('$')) // ; // interpolation_scheme = ignore_section; // element_data = ignore_section; // node_data = ignore_section; // version // = qi::int_ [ phx::push_back(lbs::_val, lbs::_1) ] // >> *( qi::char_(".") >> qi::int_ [ phx::push_back(lbs::_val, lbs::_1) ] ) // ; // position // = real [ phx::push_back(lbs::_val, lbs::_1) ] // > real [ phx::push_back(lbs::_val, lbs::_1) ] // > real [ phx::push_back(lbs::_val, lbs::_1) ] // ; // tags // = qi::int_ [ lbs::_a = lbs::_1 ] // > qi::repeat(phx::val(lbs::_a))[ qi::int_ [ phx::push_back(lbs::_val, // lbs::_1) ] ] // ; // element // = ( qi::int_ [ lbs::_a = lbs::_1 ] // > msh_element_type [ lbs::_b = lazy_get_nb_nodes(lbs::_1) ] // > tags [ lbs::_c = lbs::_1 ] // > connectivity(lbs::_a) [ lbs::_d = lbs::_1 ] // ) [ lbs::_val = lazy_element(lbs::_a, // phx::cref(lbs::_b), // phx::cref(lbs::_c), // phx::cref(lbs::_d)) ] // ; // connectivity // = qi::repeat(lbs::_r1)[ qi::int_ [ phx::push_back(lbs::_val, // lbs::_1) ] ] // ; // sections.add // ("MeshFormat", &mesh_format) // ("Nodes", &nodes) // ("Elements", &elements) // ("PhysicalNames", &physical_names) // ("InterpolationScheme", &interpolation_scheme) // ("ElementData", &element_data) // ("NodeData", &node_data); // msh_element_type.add // ("0" , _not_defined ) // ("1" , _segment_2 ) // ("2" , _triangle_3 ) // ("3" , _quadrangle_4 ) // ("4" , _tetrahedron_4 ) // ("5" , _hexahedron_8 ) // ("6" , _pentahedron_6 ) // ("7" , _not_defined ) // ("8" , _segment_3 ) // ("9" , _triangle_6 ) // ("10", _not_defined ) // ("11", _tetrahedron_10) // ("12", _not_defined ) // ("13", _not_defined ) // ("14", _hexahedron_20 ) // ("15", _pentahedron_15) // ("16", _not_defined ) // ("17", _point_1 ) // ("18", _quadrangle_8 ); // mesh_format .name("MeshFormat" ); // nodes .name("Nodes" ); // elements .name("Elements" ); // physical_names .name("PhysicalNames" ); // interpolation_scheme.name("InterpolationScheme"); // element_data .name("ElementData" ); // node_data .name("NodeData" ); // clang-format on // } // /* ---------------------------------------------------------------------- // */ // /* Rules */ // /* ---------------------------------------------------------------------- // */ // private: // qi::symbols<char, ElementType> msh_element_type; // qi::symbols<char, qi::rule<Iterator, void(), Skipper> *> sections; // qi::rule<Iterator, void(), Skipper> start; // qi::rule<Iterator, void(), Skipper, qi::locals<std::string> > // unknown_section; // qi::rule<Iterator, void(), Skipper, qi::locals<qi::rule<Iterator, // Skipper> *> > known_section; // qi::rule<Iterator, void(), Skipper> mesh_format, nodes, elements, // physical_names, ignore_section, // interpolation_scheme, element_data, node_data, any_line; // qi::rule<Iterator, void(), Skipper, qi::locals<int> > nodes_; // qi::rule<Iterator, void(), Skipper, qi::locals< int, int, vector<int>, // vector<int> > > elements_; // qi::rule<Iterator, std::vector<int>(), Skipper> version; // qi::rule<Iterator, _Element(), Skipper, qi::locals<ElementType> > // element; // qi::rule<Iterator, std::vector<int>(), Skipper, qi::locals<int> > tags; // qi::rule<Iterator, std::vector<int>(int), Skipper> connectivity; // qi::rule<Iterator, std::vector<Real>(), Skipper> position; // qi::real_parser<Real, qi::real_policies<Real> > real; // /* ---------------------------------------------------------------------- // */ // /* Members */ // /* ---------------------------------------------------------------------- // */ // private: // /// reference to the mesh to read // Mesh & mesh; // /// correspondance between the numbering of nodes in the abaqus file and // in // /// the akantu mesh // std::map<UInt, UInt> msh_nodes_to_akantu; // /// correspondance between the element number in the abaqus file and the // /// Element in the akantu mesh // std::map<UInt, Element> msh_elemt_to_akantu; // }; // } // /* -------------------------------------------------------------------------- // */ // void MeshIOAbaqus::read(const std::string& filename, Mesh& mesh) { // namespace qi = boost::spirit::qi; // namespace ascii = boost::spirit::ascii; // std::ifstream infile; // infile.open(filename.c_str()); // if(!infile.good()) { // AKANTU_DEBUG_ERROR("Cannot open file " << filename); // } // std::string storage; // We will read the contents here. // infile.unsetf(std::ios::skipws); // No white space skipping! // std::copy(std::istream_iterator<char>(infile), // std::istream_iterator<char>(), // std::back_inserter(storage)); // typedef std::string::const_iterator iterator_t; // typedef ascii::space_type skipper; // typedef _parser::MshMeshGrammar<iterator_t, skipper> grammar; // grammar g(mesh); // skipper ws; // iterator_t iter = storage.begin(); // iterator_t end = storage.end(); // qi::phrase_parse(iter, end, g, ws); // this->setNbGlobalNodes(mesh, mesh.getNodes().getSize()); // MeshUtils::fillElementToSubElementsData(mesh); // } static void my_getline(std::ifstream & infile, std::string & str) { std::string tmp_str; std::getline(infile, tmp_str); str = trim(tmp_str); } /* -------------------------------------------------------------------------- */ void MeshIOMSH::read(const std::string & filename, Mesh & mesh) { MeshAccessor mesh_accessor(mesh); std::ifstream infile; infile.open(filename.c_str()); std::string line; UInt first_node_number = std::numeric_limits<UInt>::max(), last_node_number = 0, file_format = 1, current_line = 0; bool has_physical_names = false; if (!infile.good()) { AKANTU_DEBUG_ERROR("Cannot open file " << filename); } while (infile.good()) { my_getline(infile, line); current_line++; /// read the header if (line == "$MeshFormat") { my_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."); my_getline(infile, line); /// the end of block line current_line += 2; file_format = 2; } /// read the physical names if (line == "$PhysicalNames") { has_physical_names = true; my_getline(infile, line); /// the format line std::stringstream sstr(line); UInt num_of_phys_names; sstr >> num_of_phys_names; for (UInt k(0); k < num_of_phys_names; k++) { my_getline(infile, line); std::stringstream sstr_phys_name(line); UInt phys_name_id; UInt phys_dim; sstr_phys_name >> phys_dim >> phys_name_id; std::size_t b = line.find("\""); std::size_t e = line.rfind("\""); std::string phys_name = line.substr(b + 1, e - b - 1); phys_name_map[phys_name_id] = phys_name; } } /// read all nodes if (line == "$Nodes" || line == "$NOD") { UInt nb_nodes; my_getline(infile, line); std::stringstream sstr(line); sstr >> nb_nodes; current_line++; Array<Real> & nodes = mesh_accessor.getNodes(); nodes.resize(nb_nodes); mesh_accessor.setNbGlobalNodes(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; my_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.storage()[offset + j] = coord[j]; } my_getline(infile, line); /// the end of block line } /// read all elements if (line == "$Elements" || line == "$ELM") { UInt nb_elements; std::vector<UInt> read_order; my_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; Array<UInt> * connectivity = NULL; UInt node_per_element = 0; for (UInt i = 0; i < nb_elements; ++i) { my_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 = this->_msh_to_akantu_element_types[(MSHElementType)msh_type]; if (akantu_type == _not_defined) { AKANTU_DEBUG_WARNING("Unsuported element kind " << msh_type << " at line " << current_line); continue; } if (akantu_type != akantu_type_old) { connectivity = &mesh_accessor.getConnectivity(akantu_type); // connectivity->resize(0); node_per_element = connectivity->getNbComponent(); akantu_type_old = akantu_type; read_order = this->_read_order[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; Array<UInt> * data = mesh.getDataPointer<UInt>( sstr_tag_name.str(), akantu_type, _not_ghost); data->push_back(tag); } } else if (file_format == 1) { Int tag; sstr_elem >> tag; // reg-phys std::string tag_name = "tag_0"; Array<UInt> * data = mesh.getDataPointer<UInt>(tag_name, akantu_type, _not_ghost); data->push_back(tag); sstr_elem >> tag; // reg-elem tag_name = "tag_1"; data = mesh.getDataPointer<UInt>(tag_name, akantu_type, _not_ghost); data->push_back(tag); sstr_elem >> tag; // number-of-nodes } Vector<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[j]) = node_index; } connectivity->push_back(local_connect); } my_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); } } mesh.updateTypesOffsets(_not_ghost); infile.close(); this->constructPhysicalNames("tag_0", mesh); if (has_physical_names) mesh.createGroupsFromMeshData<std::string>("physical_names"); MeshUtils::fillElementToSubElementsData(mesh); } /* -------------------------------------------------------------------------- */ void MeshIOMSH::write(const std::string & filename, const Mesh & mesh) { std::ofstream outfile; const Array<Real> & 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<Real>::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.storage()[offset + j]; } for (UInt p = nodes.getNbComponent(); p < 3; ++p) outfile << " " << 0.; outfile << std::endl; ; } outfile << std::nouppercase; outfile << "$EndNodes" << std::endl; ; outfile << "$Elements" << std::endl; ; Mesh::type_iterator it = mesh.firstType(_all_dimensions, _not_ghost, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(_all_dimensions, _not_ghost, _ek_not_defined); Int nb_elements = 0; for (; it != end; ++it) { const Array<UInt> & connectivity = mesh.getConnectivity(*it, _not_ghost); nb_elements += connectivity.getSize(); } outfile << nb_elements << std::endl; UInt element_idx = 1; for (it = mesh.firstType(_all_dimensions, _not_ghost, _ek_not_defined); it != end; ++it) { ElementType type = *it; const Array<UInt> & connectivity = mesh.getConnectivity(type, _not_ghost); UInt * tag[2] = {NULL, NULL}; try { const Array<UInt> & data_tag_0 = mesh.getData<UInt>("tag_0", type, _not_ghost); tag[0] = data_tag_0.storage(); } catch (...) { tag[0] = NULL; } try { const Array<UInt> & data_tag_1 = mesh.getData<UInt>("tag_1", type, _not_ghost); tag[1] = data_tag_1.storage(); } catch (...) { tag[1] = NULL; } for (UInt i = 0; i < connectivity.getSize(); ++i) { UInt offset = i * connectivity.getNbComponent(); outfile << element_idx << " " << _akantu_to_msh_element_types[type] << " 2"; /// \todo write the real data in the file for (UInt t = 0; t < 2; ++t) if (tag[t]) outfile << " " << tag[t][i]; else outfile << " 0"; for (UInt j = 0; j < connectivity.getNbComponent(); ++j) { outfile << " " << connectivity.storage()[offset + j] + 1; } outfile << std::endl; element_idx++; } } outfile << "$EndElements" << std::endl; ; outfile.close(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/io/mesh_io/mesh_io_msh.hh b/src/io/mesh_io/mesh_io_msh.hh index f36eed4e4..143bd095e 100644 --- a/src/io/mesh_io/mesh_io_msh.hh +++ b/src/io/mesh_io/mesh_io_msh.hh @@ -1,115 +1,115 @@ /** * @file mesh_io_msh.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Mon Dec 07 2015 * * @brief Read/Write for MSH files * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_IO_MSH_HH__ #define __AKANTU_MESH_IO_MSH_HH__ /* -------------------------------------------------------------------------- */ #include "mesh_io.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class MeshIOMSH : public MeshIO { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshIOMSH(); virtual ~MeshIOMSH(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// read a mesh from the file virtual void read(const std::string & filename, Mesh & mesh); /// write a mesh to a file virtual void write(const std::string & filename, const Mesh & mesh); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// MSH element types enum MSHElementType { _msh_not_defined = 0, _msh_segment_2 = 1, // 2-node line. _msh_triangle_3 = 2, // 3-node triangle. _msh_quadrangle_4 = 3, // 4-node quadrangle. _msh_tetrahedron_4 = 4, // 4-node tetrahedron. _msh_hexahedron_8 = 5, // 8-node hexahedron. _msh_prism_1 = 6, // 6-node prism. _msh_pyramid_1 = 7, // 5-node pyramid. _msh_segment_3 = 8, // 3-node second order line _msh_triangle_6 = 9, // 6-node second order triangle _msh_quadrangle_9 = 10, // 9-node second order quadrangle _msh_tetrahedron_10 = 11, // 10-node second order tetrahedron _msh_hexahedron_27 = 12, // 27-node second order hexahedron _msh_prism_18 = 13, // 18-node second order prism _msh_pyramid_14 = 14, // 14-node second order pyramid _msh_point = 15, // 1-node point. _msh_quadrangle_8 = 16, // 8-node second order quadrangle _msh_hexahedron_20 = 17, // 20-node second order hexahedron _msh_prism_15 = 18 // 15-node second order prism }; #define MAX_NUMBER_OF_NODE_PER_ELEMENT 10 // tetrahedron of second order /// order in witch element as to be read std::map< ElementType, std::vector<UInt> > _read_order; /// number of nodes per msh element std::map<MSHElementType, UInt> _msh_nodes_per_elem; /// correspondence between msh element types and akantu element types std::map<MSHElementType, ElementType> _msh_to_akantu_element_types; /// correspondence between akantu element types and msh element types std::map<ElementType, MSHElementType> _akantu_to_msh_element_types; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MESH_IO_MSH_HH__ */ diff --git a/src/io/mesh_io/mesh_io_msh_struct.cc b/src/io/mesh_io/mesh_io_msh_struct.cc index b774895c3..05d02f96c 100644 --- a/src/io/mesh_io/mesh_io_msh_struct.cc +++ b/src/io/mesh_io/mesh_io_msh_struct.cc @@ -1,80 +1,80 @@ /** * @file mesh_io_msh_struct.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Mon Dec 07 2015 * * @brief Read/Write for MSH files generated by gmsh * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "mesh_io.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { MeshIOMSHStruct::MeshIOMSHStruct() : MeshIOMSH() { canReadSurface = true; canReadExtendedData = true; _msh_to_akantu_element_types.clear(); _msh_to_akantu_element_types[_msh_not_defined ] = _not_defined; _msh_to_akantu_element_types[_msh_segment_2 ] = _bernoulli_beam_2; _msh_to_akantu_element_types[_msh_triangle_3 ] = _kirchhoff_shell; _akantu_to_msh_element_types.clear(); _akantu_to_msh_element_types[_not_defined ] = _msh_not_defined; _akantu_to_msh_element_types[_bernoulli_beam_2] = _msh_segment_2; _akantu_to_msh_element_types[_bernoulli_beam_3] = _msh_segment_2; _akantu_to_msh_element_types[_kirchhoff_shell] = _msh_triangle_3; std::map<ElementType, MSHElementType>::iterator it; for(it = _akantu_to_msh_element_types.begin(); it != _akantu_to_msh_element_types.end(); ++it) { UInt nb_nodes = _msh_nodes_per_elem[it->second]; std::vector<UInt> tmp(nb_nodes); for (UInt i = 0; i < nb_nodes; ++i) tmp[i] = i; _read_order[it->first] = tmp; } } /* -------------------------------------------------------------------------- */ void MeshIOMSHStruct::read(const std::string & filename, Mesh & mesh) { if(mesh.getSpatialDimension() == 2) { _msh_to_akantu_element_types[_msh_segment_2 ] = _bernoulli_beam_2; } else if (mesh.getSpatialDimension() == 3) { _msh_to_akantu_element_types[_msh_segment_2 ] = _bernoulli_beam_3; AKANTU_DEBUG_WARNING("The MeshIOMSHStruct is reading bernoulli beam 3D be sure to provide the missing normals"); } MeshIOMSH::read(filename, mesh); } -__END_AKANTU__ +} // akantu diff --git a/src/io/mesh_io/mesh_io_msh_struct.hh b/src/io/mesh_io/mesh_io_msh_struct.hh index 698b8e73e..2a30df9a5 100644 --- a/src/io/mesh_io/mesh_io_msh_struct.hh +++ b/src/io/mesh_io/mesh_io_msh_struct.hh @@ -1,56 +1,56 @@ /** * @file mesh_io_msh_struct.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief Read/Write for MSH files * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_IO_MSH_STRUCT_HH__ #define __AKANTU_MESH_IO_MSH_STRUCT_HH__ -__BEGIN_AKANTU__ +namespace akantu { class MeshIOMSHStruct : public MeshIOMSH { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshIOMSHStruct(); /// read a mesh from the file virtual void read(const std::string & filename, Mesh & mesh); }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MESH_IO_MSH_STRUCT_HH__ */ diff --git a/src/io/model_io.cc b/src/io/model_io.cc index 12a2e72d2..edfd6c372 100644 --- a/src/io/model_io.cc +++ b/src/io/model_io.cc @@ -1,50 +1,50 @@ /** * @file model_io.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Sun Oct 19 2014 * * @brief Reader for models (this is deprecated) * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "model_io.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ ModelIO::ModelIO() { } /* -------------------------------------------------------------------------- */ ModelIO::~ModelIO() { } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/io/model_io.hh b/src/io/model_io.hh index 42892f73e..f008df2c5 100644 --- a/src/io/model_io.hh +++ b/src/io/model_io.hh @@ -1,82 +1,82 @@ /** * @file model_io.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief Reader for models (this is deprecated) * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_MODEL_IO_HH__ #define __AKANTU_MODEL_IO_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "model.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class ModelIO { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ModelIO(); virtual ~ModelIO(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// read a model from file virtual void read(const std::string & filename, Model & model) = 0; /// write a mesh to a file virtual void write(const std::string & filename, const Model & model) = 0; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MODEL_IO_HH__ */ diff --git a/src/io/model_io/model_io_ibarras.cc b/src/io/model_io/model_io_ibarras.cc index 62a8eaf24..e30831808 100644 --- a/src/io/model_io/model_io_ibarras.cc +++ b/src/io/model_io/model_io_ibarras.cc @@ -1,313 +1,313 @@ /** * @file model_io_ibarras.cc * * @author Fabian Barras <fabian.barras@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Fri Jan 22 2016 * * @brief Mesh Reader specially created for Wood's Tower analysis performed by * the Institute I-Barras * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include <fstream> #include <iostream> /* -------------------------------------------------------------------------- */ #include "model_io_ibarras.hh" #include "static_communicator.hh" #include "aka_math.hh" #include "static_communicator.hh" #include "sparse_matrix.hh" #include "solver.hh" #include "integration_scheme_2nd_order.hh" /* -------------------------------------------------------------------------- */ #include <string.h> /* -------------------------------------------------------------------------- */ #include <stdio.h> -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* Methods Implentations */ /* -------------------------------------------------------------------------- */ void ModelIOIBarras::read(const std::string & filename, Model & mod) { if (!dynamic_cast<StructuralMechanicsModel *>(&mod)) { AKANTU_DEBUG_ERROR(""); } StructuralMechanicsModel & model = static_cast<StructuralMechanicsModel &>(mod); Mesh * mesh = new Mesh(3); std::ifstream infile; infile.open(filename.c_str()); std::string line; UInt current_line = 0; if (!infile.good()) { AKANTU_DEBUG_ERROR("Cannot open file " << filename); } // Get Nodes Position std::getline(infile, line); current_line++; std::stringstream sstr(line); UInt nb_nodes; sstr >> nb_nodes; const UInt spatial_dimension = 3; Real coord[spatial_dimension]; Real * temp_nodes = new Real[nb_nodes * spatial_dimension]; UInt * connect_to_akantu = new UInt[nb_nodes]; std::fill_n(connect_to_akantu, 0, nb_nodes); std::fill_n(temp_nodes, 0., nb_nodes * spatial_dimension); for (UInt i = 0; i < nb_nodes; ++i) { UInt offset = i * spatial_dimension; std::getline(infile, line); std::stringstream sstr_node(line); sstr_node >> coord[0] >> coord[1] >> coord[2]; current_line++; /// read the coordinates of structural nodes and help nodes for (UInt j = 0; j < spatial_dimension; ++j) temp_nodes[offset + j] = coord[j]; } // Get Connectivities std::getline(infile, line); current_line++; std::stringstream sstr_elem(line); UInt nb_elements; sstr_elem >> nb_elements; mesh->addConnectivityType(_bernoulli_beam_3); Array<UInt> & connectivity = const_cast<Array<UInt> &>(mesh->getConnectivity(_bernoulli_beam_3)); connectivity.resize(nb_elements); UInt nonodes[2]; UInt nb_struct_nodes = 1; for (UInt i = 0; i < nb_elements; ++i) { std::getline(infile, line); std::stringstream sstr_element(line); sstr_element >> nonodes[0] >> nonodes[1]; current_line++; /// read the connectivities for (UInt j = 0; j < 2; ++j) { if (connect_to_akantu[nonodes[j] - 1] == 0) { connect_to_akantu[nonodes[j] - 1] = nb_struct_nodes; ++nb_struct_nodes; } connectivity(i, j) = connect_to_akantu[nonodes[j] - 1] - 1; } } nb_struct_nodes -= 1; /// read the coordinates of structural nodes Array<Real> & nodes = const_cast<Array<Real> &>(mesh->getNodes()); nodes.resize(nb_struct_nodes); for (UInt k = 0; k < nb_nodes; ++k) { if (connect_to_akantu[k] != 0) { for (UInt j = 0; j < spatial_dimension; ++j) nodes(connect_to_akantu[k] - 1, j) = temp_nodes[k * spatial_dimension + j]; } } // MeshPartitionScotch partition(*mesh, spatial_dimension); // partition.reorder(); /// Apply Boundaries model.registerFEEngineObject<StructuralMechanicsModel::MyFEEngineType>( "StructuralMechanicsModel", *mesh, spatial_dimension); model.initModel(); model.initArrays(); Array<bool> & blocked_dofs = model.getBlockedDOFs(); std::getline(infile, line); std::stringstream sstr_nb_boundaries(line); UInt nb_boundaries; sstr_nb_boundaries >> nb_boundaries; current_line++; for (UInt i = 0; i < nb_boundaries; ++i) { std::getline(infile, line); std::stringstream sstr_boundary(line); UInt boundnary_node; sstr_boundary >> boundnary_node; current_line++; for (UInt j = 0; j < spatial_dimension; ++j) blocked_dofs(connect_to_akantu[boundnary_node - 1] - 1, j) = true; } /// Define Materials std::getline(infile, line); std::stringstream sstr_nb_materials(line); UInt nb_materials; sstr_nb_materials >> nb_materials; current_line++; for (UInt i = 0; i < nb_materials; ++i) { std::getline(infile, line); std::stringstream sstr_material(line); Real material[6]; sstr_material >> material[0] >> material[1] >> material[2] >> material[3] >> material[4] >> material[5]; current_line++; StructuralMaterial mat; mat.E = material[0]; mat.GJ = material[1] * material[2]; mat.Iy = material[3]; mat.Iz = material[4]; mat.A = material[5]; model.addMaterial(mat); } /// Apply normals and Material TO IMPLEMENT UInt property[2]; Array<UInt> & element_material = model.getElementMaterial(_bernoulli_beam_3); mesh->initNormals(); Array<Real> & normals = const_cast<Array<Real> &>(mesh->getNormals(_bernoulli_beam_3)); normals.resize(nb_elements); for (UInt i = 0; i < nb_elements; ++i) { std::getline(infile, line); std::stringstream sstr_properties(line); sstr_properties >> property[0] >> property[1]; current_line++; /// Assign material element_material(i) = property[0] - 1; /// Compute normals Real x[3]; Real v[3]; Real w[3]; Real n[3]; if (property[1] == 0) { for (UInt j = 0; j < spatial_dimension; ++j) { x[j] = nodes(connectivity(i, 1), j) - nodes(connectivity(i, 0), j); } n[0] = x[1]; n[1] = -x[0]; n[2] = 0.; } else { for (UInt j = 0; j < spatial_dimension; ++j) { x[j] = nodes(connectivity(i, 1), j) - nodes(connectivity(i, 0), j); v[j] = nodes(connectivity(i, 1), j) - temp_nodes[(property[1] - 1) * spatial_dimension + j]; Math::vectorProduct3(x, v, w); Math::vectorProduct3(x, w, n); } } Math::normalize3(n); for (UInt j = 0; j < spatial_dimension; ++j) { normals(i, j) = n[j]; } } model.computeRotationMatrix(_bernoulli_beam_3); infile.close(); } /* -------------------------------------------------------------------------- */ void ModelIOIBarras::assign_sets(const std::string & filename, StructuralMechanicsModel & model) { std::ifstream infile; infile.open(filename.c_str()); std::string line; UInt current_line = 0; if (!infile.good()) { AKANTU_DEBUG_ERROR("Cannot open file " << filename); } // Define Sets of Beams Array<UInt> & set_ID = model.getSet_ID(_bernoulli_beam_3); set_ID.clear(); std::getline(infile, line); std::stringstream sstr_nb_sets(line); UInt nb_sets; sstr_nb_sets >> nb_sets; current_line++; UInt no_element[2]; for (UInt i = 0; i < nb_sets; ++i) { std::getline(infile, line); std::stringstream sstr_set(line); sstr_set >> no_element[0]; no_element[1] = no_element[0]; sstr_set >> no_element[1]; while (no_element[0] != 0) { for (UInt j = no_element[0] - 1; j < no_element[1]; ++j) { set_ID(j) = i + 1; } std::getline(infile, line); std::stringstream sstr_sets(line); sstr_sets >> no_element[0]; no_element[1] = no_element[0]; sstr_sets >> no_element[1]; } } } -__END_AKANTU__ +} // akantu diff --git a/src/io/model_io/model_io_ibarras.hh b/src/io/model_io/model_io_ibarras.hh index 03535edf2..b86399428 100644 --- a/src/io/model_io/model_io_ibarras.hh +++ b/src/io/model_io/model_io_ibarras.hh @@ -1,65 +1,65 @@ /** * @file model_io_ibarras.hh * * @author Fabian Barras <fabian.barras@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief ModelIO implementation for IBarras input files * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MODEL_IO_IBARRAS_HH__ #define __AKANTU_MODEL_IO_IBARRAS_HH__ /* -------------------------------------------------------------------------- */ #include "model_io.hh" #include "structural_mechanics_model.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class ModelIOIBarras : public ModelIO { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ModelIOIBarras(){}; virtual ~ModelIOIBarras(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// read a model from the file virtual void read(const std::string & filename, Model & model); /// assign sets of member to an already constructed model virtual void assign_sets(const std::string & filename, StructuralMechanicsModel & model); }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MODEL_IO_IBARRAS_HH__ */ diff --git a/src/io/parser/input_file_parser.hh b/src/io/parser/input_file_parser.hh index 8a4bbe997..3494dae39 100644 --- a/src/io/parser/input_file_parser.hh +++ b/src/io/parser/input_file_parser.hh @@ -1,263 +1,263 @@ /** * @file input_file_parser.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Tue May 19 2015 * * @brief Grammar definition for the input files * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ // Boost /* -------------------------------------------------------------------------- */ #include <boost/config/warning_disable.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_fusion.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <boost/spirit/include/phoenix_bind.hpp> #include <boost/variant/recursive_variant.hpp> #ifndef __AKANTU_INPUT_FILE_PARSER_HH__ #define __AKANTU_INPUT_FILE_PARSER_HH__ namespace spirit = boost::spirit; namespace qi = boost::spirit::qi; namespace lbs = boost::spirit::qi::labels; namespace ascii = boost::spirit::ascii; namespace phx = boost::phoenix; -__BEGIN_AKANTU__ +namespace akantu { namespace parser { struct error_handler_ { template <typename, typename, typename, typename> struct result { typedef void type; }; template <typename Iterator> void operator()(qi::info const & what, Iterator err_pos, __attribute__((unused)) Iterator first, __attribute__((unused)) Iterator last) const { spirit::classic::file_position pos = err_pos.get_position(); AKANTU_EXCEPTION("Parse error [ " << "Expecting " << what << " instead of \"" << *err_pos << "\" ]" << " in file " << pos.file << " line " << pos.line << " column " << pos.column << std::endl << "'" << err_pos.get_currentline() << "'" << std::endl << std::setw(pos.column) << " " << "^- here"); } private: }; static ParserSection & create_subsection(const SectionType & type, const std::string & name, const boost::optional<std::string> & option, ParserSection & sect) { std::string opt = ""; if (option) opt = *option; ParserSection sect_tmp(name, type, opt, sect); return sect.addSubSection(sect_tmp); } template <typename Iter> static bool create_parameter(boost::iterator_range<Iter> & rng, std::string & value, ParserSection & sect) { try { std::string name(rng.begin(), rng.end()); name = trim(name); spirit::classic::file_position pos = rng.begin().get_position(); ParserParameter param_tmp(name, value, sect); param_tmp.setDebugInfo(pos.file, pos.line, pos.column); sect.addParameter(param_tmp); } catch (debug::Exception & e) { return false; } return true; } static std::string concatenate(const std::string & t1, const std::string & t2) { return (t1 + t2); } /* ---------------------------------------------------------------------- */ /* Grammars definitions */ /* ---------------------------------------------------------------------- */ template <class Iterator> struct InputFileGrammar : qi::grammar<Iterator, void(), typename Skipper<Iterator>::type> { InputFileGrammar(ParserSection * sect) : InputFileGrammar::base_type(start, "input_file_grammar"), parent_section(sect) { /* clang-format off */ start = mini_section(parent_section) ; mini_section = *( entry (lbs::_r1) | section(lbs::_r1) ) ; entry = ( qi::raw[key] >> '=' > value ) [ lbs::_pass = phx::bind(&create_parameter<Iterator>, lbs::_1, lbs::_2, *lbs::_r1) ] ; section = ( qi::no_case[section_type] > qi::lexeme [ section_name > -section_option ] ) [ lbs::_a = &phx::bind(&create_subsection, lbs::_1, phx::at_c<0>(lbs::_2), phx::at_c<1>(lbs::_2), *lbs::_r1) ] > '[' > mini_section(lbs::_a) > ']' ; section_name = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9") ; section_option = (+ascii::space >> section_name) [ lbs::_val = lbs::_2 ] ; key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9") ; value = ( mono_line_value [ lbs::_a = phx::bind(&concatenate, lbs::_a, lbs::_1) ] > *( '\\' > mono_line_value [ lbs::_a = phx::bind(&concatenate, lbs::_a, lbs::_1) ] ) ) [ lbs::_val = lbs::_a ] ; mono_line_value = qi::lexeme [ +(qi::char_ - (qi::char_('=') | spirit::eol | '#' | ';' | '\\')) ] ; skipper = ascii::space | "#" >> *(qi::char_ - spirit::eol) ; /* clang-format on */ #define AKANTU_SECTION_TYPE_ADD(r, data, elem) \ (BOOST_PP_STRINGIZE(elem), AKANTU_SECTION_TYPES_PREFIX(elem)) section_type.add BOOST_PP_SEQ_FOR_EACH(AKANTU_SECTION_TYPE_ADD, _, AKANTU_SECTION_TYPES); #undef AKANTU_SECTION_TYPE_ADD #if !defined(AKANTU_NDEBUG) && defined(AKANTU_CORE_CXX_11) phx::function<error_handler_> const error_handler = error_handler_(); qi::on_error<qi::fail>(start, error_handler(lbs::_4, lbs::_3, lbs::_1, lbs::_2)); #endif section.name("section"); section_name.name("section-name"); section_option.name("section-option"); mini_section.name("section-content"); entry.name("parameter"); key.name("parameter-name"); value.name("parameter-value"); section_type.name("section-types-list"); mono_line_value.name("mono-line-value"); #if !defined AKANTU_NDEBUG if (AKANTU_DEBUG_TEST(dblDebug)) { // qi::debug(section); qi::debug(section_name); qi::debug(section_option); // qi::debug(mini_section); // qi::debug(entry); qi::debug(key); qi::debug(value); qi::debug(mono_line_value); } #endif } const std::string & getErrorMessage() const { return error_message; }; typedef typename Skipper<Iterator>::type skipper_type; skipper_type skipper; private: std::string error_message; qi::rule<Iterator, void(ParserSection *), skipper_type> mini_section; qi::rule<Iterator, void(ParserSection *), qi::locals<ParserSection *>, skipper_type> section; qi::rule<Iterator, void(), skipper_type> start; qi::rule<Iterator, std::string()> section_name; qi::rule<Iterator, std::string()> section_option; qi::rule<Iterator, void(ParserSection *), skipper_type> entry; qi::rule<Iterator, std::string(), skipper_type> key; qi::rule<Iterator, std::string(), qi::locals<std::string>, skipper_type> value; qi::rule<Iterator, std::string(), skipper_type> mono_line_value; qi::symbols<char, SectionType> section_type; ParserSection * parent_section; }; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_INPUT_FILE_PARSER_HH__ */ diff --git a/src/io/parser/parameter_registry.cc b/src/io/parser/parameter_registry.cc index ac1db11e8..264ef1822 100644 --- a/src/io/parser/parameter_registry.cc +++ b/src/io/parser/parameter_registry.cc @@ -1,152 +1,152 @@ /** * @file parameter_registry.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Thu Nov 19 2015 * * @brief Parameter Registry and derived classes implementation * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "parameter_registry.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { Parameter::Parameter() : name(""), description(""), param_type(_pat_internal) {} /* -------------------------------------------------------------------------- */ Parameter::Parameter(std::string name, std::string description, ParameterAccessType param_type) : name(name), description(description), param_type(param_type) {} /* -------------------------------------------------------------------------- */ bool Parameter::isWritable() const { return param_type & _pat_writable; } /* -------------------------------------------------------------------------- */ bool Parameter::isReadable() const { return param_type & _pat_readable; } /* -------------------------------------------------------------------------- */ bool Parameter::isInternal() const { return param_type & _pat_internal; } /* -------------------------------------------------------------------------- */ bool Parameter::isParsable() const { return param_type & _pat_parsable; } /* -------------------------------------------------------------------------- */ void Parameter::setAccessType(ParameterAccessType ptype) { this->param_type = ptype; } /* -------------------------------------------------------------------------- */ void Parameter::printself(std::ostream & stream) const { stream << " "; if (isInternal()) stream << "iii"; else { if (isReadable()) stream << "r"; else stream << "-"; if (isWritable()) stream << "w"; else stream << "-"; if (isParsable()) stream << "p"; else stream << "-"; } stream << " "; std::stringstream sstr; sstr << name; UInt width = std::max(int(10 - sstr.str().length()), 0); sstr.width(width); if (description != "") { sstr << " [" << description << "]"; } stream << sstr.str(); width = std::max(int(50 - sstr.str().length()), 0); stream.width(width); stream << " : "; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ ParameterRegistry::ParameterRegistry() : consisder_sub(true) { } /* -------------------------------------------------------------------------- */ ParameterRegistry::~ParameterRegistry() { std::map<std::string, Parameter *>::iterator it, end; for (it = params.begin(); it != params.end(); ++it) { delete it->second; it->second = NULL; } this->params.clear(); } /* -------------------------------------------------------------------------- */ void ParameterRegistry::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; Parameters::const_iterator it; for (it = params.begin(); it != params.end(); ++it) { stream << space; it->second->printself(stream); } SubRegisteries::const_iterator sub_it; for (sub_it = sub_registries.begin(); sub_it != sub_registries.end(); ++sub_it) { stream << space << "Registry [" << std::endl; sub_it->second->printself(stream, indent + 1); stream << space << "]"; } } /* -------------------------------------------------------------------------- */ void ParameterRegistry::registerSubRegistry(const ID & id, ParameterRegistry & registry) { sub_registries[id] = ®istry; } /* -------------------------------------------------------------------------- */ void ParameterRegistry::setParameterAccessType(const std::string & name, ParameterAccessType ptype) { Parameters::iterator it = params.find(name); if (it == params.end()) AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name)); Parameter & param = *(it->second); param.setAccessType(ptype); } -__END_AKANTU__ +} // akantu diff --git a/src/io/parser/parameter_registry.hh b/src/io/parser/parameter_registry.hh index b74fc48fb..8bc290a48 100644 --- a/src/io/parser/parameter_registry.hh +++ b/src/io/parser/parameter_registry.hh @@ -1,195 +1,195 @@ /** * @file parameter_registry.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Aug 09 2012 * @date last modification: Thu Dec 17 2015 * * @brief Interface of the parameter registry * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "parser.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_PARAMETER_REGISTRY_HH__ #define __AKANTU_PARAMETER_REGISTRY_HH__ namespace akantu { class ParserParameter; } -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /// Defines the access modes of parsable parameters enum ParameterAccessType { _pat_internal = 0x0001, _pat_writable = 0x0010, _pat_readable = 0x0100, _pat_modifiable = 0x0110, //_pat_readable | _pat_writable, _pat_parsable = 0x1000, _pat_parsmod = 0x1110 //< _pat_parsable | _pat_modifiable }; /// Bit-wise operator between access modes inline ParameterAccessType operator|(const ParameterAccessType & a, const ParameterAccessType & b) { ParameterAccessType tmp = ParameterAccessType(UInt(a) | UInt(b)); return tmp; } /* -------------------------------------------------------------------------- */ template <typename T> class ParameterTyped; /** * Interface for the Parameter */ class Parameter { public: Parameter(); Parameter(std::string name, std::string description, ParameterAccessType param_type); virtual ~Parameter(){}; /* ------------------------------------------------------------------------ */ bool isInternal() const; bool isWritable() const; bool isReadable() const; bool isParsable() const; void setAccessType(ParameterAccessType ptype); /* ------------------------------------------------------------------------ */ template <typename T, typename V> void set(const V & value); virtual void setAuto(const ParserParameter & param); template <typename T> T & get(); template <typename T> const T & get() const; template <typename T> inline operator T() const; /* ------------------------------------------------------------------------ */ virtual void printself(std::ostream & stream) const; protected: /// Returns const instance of templated sub-class ParameterTyped template <typename T> const ParameterTyped<T> & getParameterTyped() const; /// Returns instance of templated sub-class ParameterTyped template <typename T> ParameterTyped<T> & getParameterTyped(); private: /// Name of parameter std::string name; /// Description of parameter std::string description; /// Type of access ParameterAccessType param_type; }; /* -------------------------------------------------------------------------- */ /* Typed Parameter */ /* -------------------------------------------------------------------------- */ /** * Type parameter transfering a ParserParameter (string: string) to a typed * parameter in the memory of the p */ template <typename T> class ParameterTyped : public Parameter { public: ParameterTyped(std::string name, std::string description, ParameterAccessType param_type, T & param); /* ------------------------------------------------------------------------ */ template <typename V> void setTyped(const V & value); void setAuto(const ParserParameter & param); T & getTyped(); const T & getTyped() const; virtual void printself(std::ostream & stream) const; private: /// Value of parameter T & param; }; /* -------------------------------------------------------------------------- */ /* Parsable Interface */ /* -------------------------------------------------------------------------- */ /// Defines interface for classes to manipulate parsable parameters class ParameterRegistry { public: ParameterRegistry(); virtual ~ParameterRegistry(); /* ------------------------------------------------------------------------ */ /// Add parameter to the params map template <typename T> void registerParam(std::string name, T & variable, ParameterAccessType type, const std::string description = ""); /// Add parameter to the params map (with default value) template <typename T> void registerParam(std::string name, T & variable, const T & default_value, ParameterAccessType type, const std::string description = ""); /*------------------------------------------------------------------------- */ protected: void registerSubRegistry(const ID & id, ParameterRegistry & registry); /* ------------------------------------------------------------------------ */ public: /// Set value to a parameter (with possible different type) template <typename T, typename V> void setMixed(const std::string & name, const V & value); /// Set value to a parameter template <typename T> void set(const std::string & name, const T & value); /// Get value of a parameter inline const Parameter & get(const std::string & name) const; protected: template <typename T> T & get(const std::string & name); protected: void setParameterAccessType(const std::string & name, ParameterAccessType ptype); /* ------------------------------------------------------------------------ */ virtual void printself(std::ostream & stream, int indent) const; protected: /// Parameters map typedef std::map<std::string, Parameter *> Parameters; Parameters params; /// list of sub-registries typedef std::map<std::string, ParameterRegistry *> SubRegisteries; SubRegisteries sub_registries; /// should accessor check in sub registries bool consisder_sub; }; -__END_AKANTU__ +} // akantu #include "parameter_registry_tmpl.hh" #endif /* __AKANTU_PARAMETER_REGISTRY_HH__ */ diff --git a/src/io/parser/parameter_registry_tmpl.hh b/src/io/parser/parameter_registry_tmpl.hh index ab806ed0b..8c7d07b08 100644 --- a/src/io/parser/parameter_registry_tmpl.hh +++ b/src/io/parser/parameter_registry_tmpl.hh @@ -1,301 +1,301 @@ /** * @file parameter_registry_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Aug 09 2012 * @date last modification: Fri Mar 27 2015 * * @brief implementation of the templated part of ParameterRegistry class and * the derivated ones * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_error.hh" #include "parser.hh" /* -------------------------------------------------------------------------- */ #include <string> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { namespace debug { class ParameterException : public Exception { public: ParameterException(const std::string & name, const std::string & message) : Exception(message), name(name) {} const std::string & name; }; class ParameterUnexistingException : public ParameterException { public: ParameterUnexistingException(const std::string & name) : ParameterException(name, "Parameter " + name + " does not exists in this scope") {} }; class ParameterAccessRightException : public ParameterException { public: ParameterAccessRightException(const std::string & name, const std::string & perm) : ParameterException(name, "Parameter " + name + " is not " + perm) {} }; class ParameterWrongTypeException : public ParameterException { public: ParameterWrongTypeException(const std::string name, const std::string & type) : ParameterException(name, "Parameter " + name + " is not of type " + type) {} }; } /* -------------------------------------------------------------------------- */ template <typename T> const ParameterTyped<T> & Parameter::getParameterTyped() const { try { const ParameterTyped<T> & tmp = dynamic_cast<const ParameterTyped<T> &>(*this); return tmp; } catch (std::bad_cast &) { AKANTU_CUSTOM_EXCEPTION(debug::ParameterWrongTypeException( name, debug::demangle(typeid(T).name()))); } } /* -------------------------------------------------------------------------- */ template <typename T> ParameterTyped<T> & Parameter::getParameterTyped() { try { ParameterTyped<T> & tmp = dynamic_cast<ParameterTyped<T> &>(*this); return tmp; } catch (...) { AKANTU_CUSTOM_EXCEPTION(debug::ParameterWrongTypeException( name, debug::demangle(typeid(T).name()))); } } /* ------------------------------------------------------------------------ */ template <typename T, typename V> void Parameter::set(const V & value) { if (!(isWritable())) AKANTU_CUSTOM_EXCEPTION( debug::ParameterAccessRightException(name, "writable")); ParameterTyped<T> & typed_param = getParameterTyped<T>(); typed_param.setTyped(value); } /* ------------------------------------------------------------------------ */ inline void Parameter::setAuto(__attribute__((unused)) const ParserParameter & value) { if (!(isParsable())) AKANTU_CUSTOM_EXCEPTION( debug::ParameterAccessRightException(name, "parsable")); } /* -------------------------------------------------------------------------- */ template <typename T> const T & Parameter::get() const { if (!(isReadable())) AKANTU_CUSTOM_EXCEPTION( debug::ParameterAccessRightException(name, "readable")); const ParameterTyped<T> & typed_param = getParameterTyped<T>(); return typed_param.getTyped(); } /* -------------------------------------------------------------------------- */ template <typename T> T & Parameter::get() { ParameterTyped<T> & typed_param = getParameterTyped<T>(); if (!(isReadable()) || !(this->isWritable())) AKANTU_CUSTOM_EXCEPTION( debug::ParameterAccessRightException(name, "accessible")); return typed_param.getTyped(); } /* -------------------------------------------------------------------------- */ template <typename T> inline Parameter::operator T() const { return this->get<T>(); } /* -------------------------------------------------------------------------- */ template <typename T> ParameterTyped<T>::ParameterTyped(std::string name, std::string description, ParameterAccessType param_type, T & param) : Parameter(name, description, param_type), param(param) {} /* -------------------------------------------------------------------------- */ template <typename T> template <typename V> void ParameterTyped<T>::setTyped(const V & value) { param = value; } /* -------------------------------------------------------------------------- */ template <typename T> inline void ParameterTyped<T>::setAuto(const ParserParameter & value) { Parameter::setAuto(value); param = static_cast<T>(value); } /* -------------------------------------------------------------------------- */ template <> inline void ParameterTyped<std::string>::setAuto(const ParserParameter & value) { Parameter::setAuto(value); param = value.getValue(); } /* -------------------------------------------------------------------------- */ template <> inline void ParameterTyped<Vector<Real>>::setAuto(const ParserParameter & in_param) { Parameter::setAuto(in_param); Vector<Real> tmp = in_param; for (UInt i = 0; i < param.size(); ++i) { param(i) = tmp(i); } } /* -------------------------------------------------------------------------- */ template <> inline void ParameterTyped<Matrix<Real>>::setAuto(const ParserParameter & in_param) { Parameter::setAuto(in_param); Matrix<Real> tmp = in_param; for (UInt i = 0; i < param.rows(); ++i) { for (UInt j = 0; j < param.cols(); ++j) { param(i, j) = tmp(i, j); } } } /* -------------------------------------------------------------------------- */ template <typename T> const T & ParameterTyped<T>::getTyped() const { return param; } /* -------------------------------------------------------------------------- */ template <typename T> T & ParameterTyped<T>::getTyped() { return param; } /* -------------------------------------------------------------------------- */ template <typename T> inline void ParameterTyped<T>::printself(std::ostream & stream) const { Parameter::printself(stream); stream << param << std::endl; } /* -------------------------------------------------------------------------- */ template <> inline void ParameterTyped<bool>::printself(std::ostream & stream) const { Parameter::printself(stream); stream << std::boolalpha << param << std::endl; } /* -------------------------------------------------------------------------- */ template <typename T> void ParameterRegistry::registerParam(std::string name, T & variable, ParameterAccessType type, const std::string description) { std::map<std::string, Parameter *>::iterator it = params.find(name); if (it != params.end()) AKANTU_CUSTOM_EXCEPTION(debug::ParameterException( name, "Parameter named " + name + " already registered.")); ParameterTyped<T> * param = new ParameterTyped<T>(name, description, type, variable); params[name] = param; } /* -------------------------------------------------------------------------- */ template <typename T> void ParameterRegistry::registerParam(std::string name, T & variable, const T & default_value, ParameterAccessType type, const std::string description) { variable = default_value; registerParam(name, variable, type, description); } /* -------------------------------------------------------------------------- */ template <typename T, typename V> void ParameterRegistry::setMixed(const std::string & name, const V & value) { std::map<std::string, Parameter *>::iterator it = params.find(name); if (it == params.end()) { if (consisder_sub) { for (SubRegisteries::iterator it = sub_registries.begin(); it != sub_registries.end(); ++it) { it->second->setMixed<T>(name, value); } } else { AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name)); } } else { Parameter & param = *(it->second); param.set<T>(value); } } /* -------------------------------------------------------------------------- */ template <typename T> void ParameterRegistry::set(const std::string & name, const T & value) { this->template setMixed<T>(name, value); } /* -------------------------------------------------------------------------- */ template <typename T> T & ParameterRegistry::get(const std::string & name) { Parameters::iterator it = params.find(name); if (it == params.end()) { if (consisder_sub) { for (SubRegisteries::iterator it = sub_registries.begin(); it != sub_registries.end(); ++it) { try { return it->second->get<T>(name); } catch (...) { } } } // nothing was found not even in sub registries AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name)); } Parameter & param = *(it->second); return param.get<T>(); } /* -------------------------------------------------------------------------- */ const Parameter & ParameterRegistry::get(const std::string & name) const { Parameters::const_iterator it = params.find(name); if (it == params.end()) { if (consisder_sub) { for (SubRegisteries::const_iterator it = sub_registries.begin(); it != sub_registries.end(); ++it) { try { return it->second->get(name); } catch (...) { } } } // nothing was found not even in sub registries AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name)); } Parameter & param = *(it->second); return param; } -__END_AKANTU__ +} // akantu diff --git a/src/io/parser/parsable.cc b/src/io/parser/parsable.cc index 511f03d81..12021b1d6 100644 --- a/src/io/parser/parsable.cc +++ b/src/io/parser/parsable.cc @@ -1,111 +1,111 @@ /** * @file parsable.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Thu Nov 19 2015 * * @brief Parsable implementation * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "parsable.hh" #include "aka_random_generator.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ Parsable::Parsable(const SectionType & section_type, const ID & id) : section_type(section_type), pid(id) { this->consisder_sub = false; } /* -------------------------------------------------------------------------- */ Parsable::~Parsable() {} /* -------------------------------------------------------------------------- */ void Parsable::registerSubSection(const SectionType & type, const std::string & name, Parsable & sub_section) { SubSectionKey key(type, name); sub_sections[key] = &sub_section; this->registerSubRegistry(name, sub_section); } /* -------------------------------------------------------------------------- */ void Parsable::parseParam(const ParserParameter & in_param) { std::map<std::string, Parameter *>::iterator it = params.find(in_param.getName()); if (it == params.end()) { if (Parser::isPermissive()) { AKANTU_DEBUG_WARNING("No parameter named " << in_param.getName() << " registered in " << pid << "."); return; } else AKANTU_EXCEPTION("No parameter named " << in_param.getName() << " registered in " << pid << "."); } Parameter & param = *(it->second); param.setAuto(in_param); } /* -------------------------------------------------------------------------- */ void Parsable::parseSection(const ParserSection & section) { if (section_type != section.getType()) AKANTU_EXCEPTION("The object " << pid << " is meant to parse section of type " << section_type << ", so it cannot parse section of type " << section.getType()); std::pair<Parser::const_parameter_iterator, Parser::const_parameter_iterator> params = section.getParameters(); Parser::const_parameter_iterator it = params.first; for (; it != params.second; ++it) { parseParam(*it); } Parser::const_section_iterator sit = section.getSubSections().first; for (; sit != section.getSubSections().second; ++sit) { parseSubSection(*sit); } } /* -------------------------------------------------------------------------- */ void Parsable::parseSubSection(const ParserSection & section) { SubSectionKey key(section.getType(), section.getName()); SubSections::iterator it = sub_sections.find(key); if (it != sub_sections.end()) { it->second->parseSection(section); } else if (!Parser::isPermissive()) { AKANTU_EXCEPTION("No parsable defined for sub sections of type <" << key.first << "," << key.second << "> in " << pid); } else AKANTU_DEBUG_WARNING("No parsable defined for sub sections of type <" << key.first << "," << key.second << "> in " << pid); } -__END_AKANTU__ +} // akantu diff --git a/src/io/parser/parsable.hh b/src/io/parser/parsable.hh index 0c4bf071c..16dfab955 100644 --- a/src/io/parser/parsable.hh +++ b/src/io/parser/parsable.hh @@ -1,76 +1,76 @@ /** * @file parameter_registry.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Aug 09 2012 * @date last modification: Thu Dec 17 2015 * * @brief Interface of the parameter registry * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "parser.hh" #include "parameter_registry.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_PARSABLE_HH__ #define __AKANTU_PARSABLE_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* Parsable Interface */ /* -------------------------------------------------------------------------- */ /// Defines interface for classes to manipulate parsable parameters class Parsable : public ParameterRegistry { public: Parsable(const SectionType & section_type, const ID & id = std::string()); virtual ~Parsable(); /// Add subsection to the sub_sections map void registerSubSection(const SectionType & type, const std::string & name, Parsable & sub_section); /* ------------------------------------------------------------------------ */ public: virtual void parseSection(const ParserSection & section); virtual void parseSubSection(const ParserSection & section); virtual void parseParam(const ParserParameter & parameter); private: SectionType section_type; /// ID of parsable object ID pid; typedef std::pair<SectionType, std::string> SubSectionKey; typedef std::map<SubSectionKey, Parsable *> SubSections; /// Subsections map SubSections sub_sections; }; -__END_AKANTU__ +} // akantu #include "parsable_tmpl.hh" #endif /* __AKANTU_PARSABLE_HH__ */ diff --git a/src/io/parser/parsable_tmpl.hh b/src/io/parser/parsable_tmpl.hh index a79d9a3be..8012ed900 100644 --- a/src/io/parser/parsable_tmpl.hh +++ b/src/io/parser/parsable_tmpl.hh @@ -1,38 +1,38 @@ /** * @file parsable_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Aug 09 2012 * @date last modification: Fri Mar 27 2015 * * @brief implementation of the templated part of ParsableParam Parsable and * ParsableParamTyped * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { -__END_AKANTU__ +} // akantu diff --git a/src/io/parser/parser.cc b/src/io/parser/parser.cc index e166b1b53..53c8eba19 100644 --- a/src/io/parser/parser.cc +++ b/src/io/parser/parser.cc @@ -1,98 +1,98 @@ /** * @file parser.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Wed Jan 13 2016 * * @brief implementation of the parser * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ // STL #include <fstream> #include <iomanip> #include <map> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "parser.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ ParserSection::~ParserSection() { this->clean(); } /* -------------------------------------------------------------------------- */ ParserParameter & ParserSection::addParameter(const ParserParameter & param) { if (parameters.find(param.getName()) != parameters.end()) AKANTU_EXCEPTION("The parameter \"" + param.getName() + "\" is already defined in this section"); return (parameters.insert(std::pair<std::string, ParserParameter>( param.getName(), param)).first->second); } /* -------------------------------------------------------------------------- */ ParserSection & ParserSection::addSubSection(const ParserSection & section) { return ((sub_sections_by_type.insert(std::pair<SectionType, ParserSection>( section.getType(), section)))->second); } /* -------------------------------------------------------------------------- */ std::string Parser::getLastParsedFile() const { return last_parsed_file; } /* -------------------------------------------------------------------------- */ void ParserSection::printself(std::ostream & stream, unsigned int indent) const { std::string space; std::string ind = AKANTU_INDENT; for (unsigned int i = 0; i < indent; i++, space += ind) ; stream << space << "Section(" << this->type << ") " << this->name << (option != "" ? (" " + option) : "") << " [" << std::endl; if (!this->parameters.empty()) { stream << space << ind << "Parameters [" << std::endl; Parameters::const_iterator pit = this->parameters.begin(); for (; pit != this->parameters.end(); ++pit) { stream << space << ind << " + "; pit->second.printself(stream); stream << std::endl; } stream << space << ind << "]" << std::endl; } if (!this->sub_sections_by_type.empty()) { stream << space << ind << "Subsections [" << std::endl; SubSections::const_iterator sit = this->sub_sections_by_type.begin(); for (; sit != this->sub_sections_by_type.end(); ++sit) sit->second.printself(stream, indent + 2); stream << std::endl; stream << space << ind << "]" << std::endl; } stream << space << "]" << std::endl; } -__END_AKANTU__ +} // akantu diff --git a/src/io/parser/parser.hh b/src/io/parser/parser.hh index a00c9d868..e1118b5ad 100644 --- a/src/io/parser/parser.hh +++ b/src/io/parser/parser.hh @@ -1,497 +1,497 @@ /** * @file parser.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Wed Jan 13 2016 * * @brief File parser interface * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_random_generator.hh" /* -------------------------------------------------------------------------- */ #include <map> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_PARSER_HH__ #define __AKANTU_PARSER_HH__ -__BEGIN_AKANTU__ +namespace akantu { #define AKANTU_SECTION_TYPES \ (global)(material)(model)(mesh)(heat)(contact)(friction)( \ embedded_interface)(rules)(non_local)(user)(solver)(neighborhood)( \ time_step_solver)(non_linear_solver)(model_solver)(integration_scheme)( \ not_defined) #define AKANTU_SECTION_TYPES_PREFIX(elem) BOOST_PP_CAT(_st_, elem) #define AKANTU_SECT_PREFIX(s, data, elem) AKANTU_SECTION_TYPES_PREFIX(elem) /// Defines the possible section types enum SectionType { BOOST_PP_SEQ_ENUM( BOOST_PP_SEQ_TRANSFORM(AKANTU_SECT_PREFIX, _, AKANTU_SECTION_TYPES)) }; #undef AKANTU_SECT_PREFIX #define AKANTU_SECTION_TYPE_PRINT_CASE(r, data, elem) \ case AKANTU_SECTION_TYPES_PREFIX(elem): { \ stream << BOOST_PP_STRINGIZE(AKANTU_SECTION_TYPES_PREFIX(elem)); \ break; \ } inline std::ostream & operator<<(std::ostream & stream, SectionType type) { switch (type) { BOOST_PP_SEQ_FOR_EACH(AKANTU_SECTION_TYPE_PRINT_CASE, _, AKANTU_SECTION_TYPES) default: stream << "not a SectionType"; break; } return stream; } #undef AKANTU_SECTION_TYPE_PRINT_CASE /// Defines the possible search contexts/scopes (for parameter search) enum ParserParameterSearchCxt { _ppsc_current_scope = 0x1, _ppsc_parent_scope = 0x2, _ppsc_current_and_parent_scope = 0x3 }; /* ------------------------------------------------------------------------ */ /* Parameters Class */ /* ------------------------------------------------------------------------ */ class ParserSection; /// @brief The ParserParameter objects represent the end of tree branches as /// they /// are the different informations contained in the input file. class ParserParameter { public: ParserParameter() : parent_section(NULL), name(std::string()), value(std::string()), dbg_filename(std::string()) {} ParserParameter(const std::string & name, const std::string & value, const ParserSection & parent_section) : parent_section(&parent_section), name(name), value(value), dbg_filename(std::string()) {} ParserParameter(const ParserParameter & param) : parent_section(param.parent_section), name(param.name), value(param.value), dbg_filename(param.dbg_filename), dbg_line(param.dbg_line), dbg_column(param.dbg_column) {} virtual ~ParserParameter() {} /// Get parameter name const std::string & getName() const { return name; } /// Get parameter value const std::string & getValue() const { return value; } /// Set info for debug output void setDebugInfo(const std::string & filename, UInt line, UInt column) { dbg_filename = filename; dbg_line = line; dbg_column = column; } template <typename T> inline operator T() const; // template <typename T> inline operator Vector<T>() const; // template <typename T> inline operator Matrix<T>() const; /// Print parameter info in stream void printself(std::ostream & stream, __attribute__((unused)) unsigned int indent = 0) const { stream << name << ": " << value << " (" << dbg_filename << ":" << dbg_line << ":" << dbg_column << ")"; } private: void setParent(const ParserSection & sect) { parent_section = § } friend class ParserSection; private: /// Pointer to the parent section const ParserSection * parent_section; /// Name of the parameter std::string name; /// Value of the parameter std::string value; /// File for debug output std::string dbg_filename; /// Position of parameter in parsed file UInt dbg_line, dbg_column; }; /* ------------------------------------------------------------------------ */ /* Sections Class */ /* ------------------------------------------------------------------------ */ /// ParserSection represents a branch of the parsing tree. class ParserSection { public: typedef std::multimap<SectionType, ParserSection> SubSections; typedef std::map<std::string, ParserParameter> Parameters; private: typedef SubSections::const_iterator const_section_iterator_; public: /* ------------------------------------------------------------------------ */ /* SubSection iterator */ /* ------------------------------------------------------------------------ */ /// Iterator on sections class const_section_iterator { public: const_section_iterator() {} const_section_iterator(const const_section_iterator & other) : it(other.it) {} const_section_iterator(const const_section_iterator_ & it) : it(it) {} const_section_iterator & operator=(const const_section_iterator & other) { if (this != &other) { it = other.it; } return *this; } const ParserSection & operator*() const { return it->second; } const ParserSection * operator->() const { return &(it->second); } bool operator==(const const_section_iterator & other) const { return it == other.it; } bool operator!=(const const_section_iterator & other) const { return it != other.it; } const_section_iterator & operator++() { ++it; return *this; } const_section_iterator operator++(int) { const_section_iterator tmp = *this; operator++(); return tmp; } private: const_section_iterator_ it; }; /* ------------------------------------------------------------------------ */ /* Parameters iterator */ /* ------------------------------------------------------------------------ */ /// Iterator on parameters class const_parameter_iterator { public: const_parameter_iterator(const const_parameter_iterator & other) : it(other.it) {} const_parameter_iterator(const Parameters::const_iterator & it) : it(it) {} const_parameter_iterator & operator=(const const_parameter_iterator & other) { if (this != &other) { it = other.it; } return *this; } const ParserParameter & operator*() const { return it->second; } const ParserParameter * operator->() { return &(it->second); }; bool operator==(const const_parameter_iterator & other) const { return it == other.it; } bool operator!=(const const_parameter_iterator & other) const { return it != other.it; } const_parameter_iterator & operator++() { ++it; return *this; } const_parameter_iterator operator++(int) { const_parameter_iterator tmp = *this; operator++(); return tmp; } private: Parameters::const_iterator it; }; /* ---------------------------------------------------------------------- */ ParserSection() : parent_section(NULL), name(std::string()), type(_st_not_defined) {} ParserSection(const std::string & name, SectionType type) : parent_section(NULL), name(name), type(type) {} ParserSection(const std::string & name, SectionType type, const std::string & option, const ParserSection & parent_section) : parent_section(&parent_section), name(name), type(type), option(option) {} ParserSection(const ParserSection & section) : parent_section(section.parent_section), name(section.name), type(section.type), option(section.option), parameters(section.parameters), sub_sections_by_type(section.sub_sections_by_type) { setChldrenPointers(); } ParserSection & operator=(const ParserSection & other) { if (&other != this) { parent_section = other.parent_section; name = other.name; type = other.type; option = other.option; parameters = other.parameters; sub_sections_by_type = other.sub_sections_by_type; setChldrenPointers(); } return *this; } virtual ~ParserSection(); virtual void printself(std::ostream & stream, unsigned int indent = 0) const; /* ---------------------------------------------------------------------- */ /* Creation functions */ /* ---------------------------------------------------------------------- */ public: ParserParameter & addParameter(const ParserParameter & param); ParserSection & addSubSection(const ParserSection & section); protected: /// Clean ParserSection content void clean() { parameters.clear(); sub_sections_by_type.clear(); } private: void setChldrenPointers() { Parameters::iterator pit = this->parameters.begin(); for (; pit != this->parameters.end(); ++pit) pit->second.setParent(*this); SubSections::iterator sit = this->sub_sections_by_type.begin(); for (; sit != this->sub_sections_by_type.end(); ++sit) sit->second.setParent(*this); } /* ---------------------------------------------------------------------- */ /* Accessors */ /* ---------------------------------------------------------------------- */ public: /// Get begin and end iterators on subsections of certain type std::pair<const_section_iterator, const_section_iterator> getSubSections(SectionType type = _st_not_defined) const { if (type != _st_not_defined) { std::pair<const_section_iterator_, const_section_iterator_> range = sub_sections_by_type.equal_range(type); return std::pair<const_section_iterator, const_section_iterator>( range.first, range.second); } else { return std::pair<const_section_iterator, const_section_iterator>( sub_sections_by_type.begin(), sub_sections_by_type.end()); } } /// Get number of subsections of certain type UInt getNbSubSections(SectionType type = _st_not_defined) const { if (type != _st_not_defined) { return this->sub_sections_by_type.count(type); } else { return this->sub_sections_by_type.size(); } } /// Get begin and end iterators on parameters std::pair<const_parameter_iterator, const_parameter_iterator> getParameters() const { return std::pair<const_parameter_iterator, const_parameter_iterator>( parameters.begin(), parameters.end()); } /* ---------------------------------------------------------------------- */ /// Get parameter within specified context const ParserParameter & getParameter( const std::string & name, ParserParameterSearchCxt search_ctx = _ppsc_current_scope) const { Parameters::const_iterator it; if (search_ctx & _ppsc_current_scope) it = parameters.find(name); if (it == parameters.end()) { if ((search_ctx & _ppsc_parent_scope) && parent_section) return parent_section->getParameter(name, search_ctx); else { AKANTU_SILENT_EXCEPTION( "The parameter " << name << " has not been found in the specified context"); } } return it->second; } /* ------------------------------------------------------------------------ */ /// Get parameter within specified context, with a default value in case the /// parameter does not exists template <class T> const T getParameter( const std::string & name, const T & default_value, ParserParameterSearchCxt search_ctx = _ppsc_current_scope) const { try { T tmp = this->getParameter(name, search_ctx); return tmp; } catch (debug::Exception &) { return default_value; } } /* ------------------------------------------------------------------------ */ /// Check if parameter exists within specified context bool hasParameter( const std::string & name, ParserParameterSearchCxt search_ctx = _ppsc_current_scope) const { Parameters::const_iterator it; if (search_ctx & _ppsc_current_scope) it = parameters.find(name); if (it == parameters.end()) { if ((search_ctx & _ppsc_parent_scope) && parent_section) return parent_section->hasParameter(name, search_ctx); else { return false; } } return true; } /* -------------------------------------------------------------------------- */ /// Get value of given parameter in context template <class T> T getParameterValue( const std::string & name, ParserParameterSearchCxt search_ctx = _ppsc_current_scope) const { const ParserParameter & tmp_param = getParameter(name, search_ctx); T t = tmp_param; return t; } /* -------------------------------------------------------------------------- */ /// Get section name const std::string getName() const { return name; } /// Get section type SectionType getType() const { return type; } /// Get section option const std::string getOption(const std::string & def = "") const { return option != "" ? option : def; } protected: void setParent(const ParserSection & sect) { parent_section = § } /* ---------------------------------------------------------------------- */ /* Members */ /* ---------------------------------------------------------------------- */ private: /// Pointer to the parent section const ParserSection * parent_section; /// Name of section std::string name; /// Type of section, see AKANTU_SECTION_TYPES SectionType type; /// Section option std::string option; /// Map of parameters in section Parameters parameters; /// Multi-map of subsections SubSections sub_sections_by_type; }; /* ------------------------------------------------------------------------ */ /* Parser Class */ /* ------------------------------------------------------------------------ */ /// Root of parsing tree, represents the global ParserSection class Parser : public ParserSection { public: Parser() : ParserSection("global", _st_global) {} void parse(const std::string & filename); std::string getLastParsedFile() const; static bool isPermissive() { return permissive_parser; } public: /// Parse real scalar static Real parseReal(const std::string & value, const ParserSection & section); /// Parse real vector static Vector<Real> parseVector(const std::string & value, const ParserSection & section); /// Parse real matrix static Matrix<Real> parseMatrix(const std::string & value, const ParserSection & section); /// Parse real random parameter static RandomParameter<Real> parseRandomParameter(const std::string & value, const ParserSection & section); protected: /// General parse function template <class T, class Grammar> static T parseType(const std::string & value, Grammar & grammar); protected: // friend class Parsable; static bool permissive_parser; std::string last_parsed_file; }; inline std::ostream & operator<<(std::ostream & stream, const ParserParameter & _this) { _this.printself(stream); return stream; } inline std::ostream & operator<<(std::ostream & stream, const ParserSection & section) { section.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #include "parser_tmpl.hh" #endif /* __AKANTU_PARSER_HH__ */ diff --git a/src/io/parser/parser_grammar_tmpl.hh b/src/io/parser/parser_grammar_tmpl.hh index fd2aefc0c..fc04f6418 100644 --- a/src/io/parser/parser_grammar_tmpl.hh +++ b/src/io/parser/parser_grammar_tmpl.hh @@ -1,81 +1,81 @@ /** * @file parser_grammar_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 11 2015 * * @brief implementation of the templated part of ParsableParam Parsable and * ParsableParamTyped * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ //#include <boost/config/warning_disable.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/support_multi_pass.hpp> #include <boost/spirit/include/classic_position_iterator.hpp> /* -------------------------------------------------------------------------- */ #ifndef AKANTU_PARSER_GRAMMAR_TMPL_HH #define AKANTU_PARSER_GRAMMAR_TMPL_HH -__BEGIN_AKANTU__ +namespace akantu { namespace qi = boost::spirit::qi; /* -------------------------------------------------------------------------- */ template <class T, class Grammar> T Parser::parseType(const std::string & value, Grammar & grammar) { using boost::spirit::ascii::space; std::string::const_iterator b = value.begin(); std::string::const_iterator e = value.end(); T resultat = T(); bool res = false; try { res = qi::phrase_parse(b, e, grammar, space, resultat); } catch(debug::Exception & ex) { AKANTU_EXCEPTION("Could not parse '" << value << "' as a " << debug::demangle(typeid(T).name()) << ", an unknown error append '" << ex.what()); } if(!res || (b != e)) { AKANTU_EXCEPTION("Could not parse '" << value << "' as a " << debug::demangle(typeid(T).name()) << ", an unknown error append '" << std::string(value.begin(), b) << "<HERE>" << std::string(b, e) << "'"); } return resultat; } namespace parser { template<class Iterator> struct Skipper { typedef qi::rule<Iterator, void()> type; }; } -__END_AKANTU__ +} // akantu #endif //AKANTU_PARSER_GRAMMAR_TMPL_HH diff --git a/src/io/parser/parser_input_files.cc b/src/io/parser/parser_input_files.cc index 3d6ebe1ef..c777bef21 100644 --- a/src/io/parser/parser_input_files.cc +++ b/src/io/parser/parser_input_files.cc @@ -1,117 +1,117 @@ /** * @file parser_input_files.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 11 2015 * @date last modification: Wed Jan 13 2016 * * @brief implementation of the parser * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ #if defined(__INTEL_COMPILER) //#pragma warning ( disable : 383 ) #elif defined (__clang__) // test clang to be sure that when we test for gnu it is only gnu #elif (defined(__GNUC__) || defined(__GNUG__)) # define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) # if GCC_VERSION > 40600 # pragma GCC diagnostic push # endif # pragma GCC diagnostic ignored "-Wunused-local-typedefs" #endif /* -------------------------------------------------------------------------- */ #include "parser.hh" #include "parser_grammar_tmpl.hh" /* -------------------------------------------------------------------------- */ #include "input_file_parser.hh" /* -------------------------------------------------------------------------- */ #include <fstream> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ void Parser::parse(const std::string & filename) { this->clean(); std::ifstream input(filename.c_str()); if (!input.good()) { AKANTU_EXCEPTION("Could not open file " << filename << "!"); } input.unsetf(std::ios::skipws); // wrap istream into iterator spirit::istream_iterator fwd_begin(input); spirit::istream_iterator fwd_end; // wrap forward iterator with position iterator, to record the position typedef spirit::classic::position_iterator2<spirit::istream_iterator> pos_iterator_type; pos_iterator_type position_begin(fwd_begin, fwd_end, filename); pos_iterator_type position_end; // parse parser::InputFileGrammar<pos_iterator_type> ag(this); bool result = qi::phrase_parse(position_begin, position_end, ag, ag.skipper); if (!result || position_begin != position_end) { spirit::classic::file_position pos = position_begin.get_position(); AKANTU_EXCEPTION("Parse error [ " << ag.getErrorMessage() << " ]" << " in file " << filename << " line " << pos.line << " column " << pos.column << std::endl << "'" << position_begin.get_currentline() << "'" << std::endl << std::setw(pos.column) << " " << "^- here"); } try { bool permissive = getParameter("permissive_parser", _ppsc_current_scope); permissive_parser = permissive; AKANTU_DEBUG_INFO("Parser switched permissive mode to " << std::boolalpha << permissive_parser); } catch (debug::Exception & e) { } last_parsed_file = filename; input.close(); } -__END_AKANTU__ +} // akantu #if defined(__INTEL_COMPILER) //#pragma warning ( disable : 383 ) #elif defined (__clang__) // test clang to be sure that when we test for gnu it is only gnu #elif defined(__GNUG__) # if GCC_VERSION > 40600 # pragma GCC diagnostic pop # else # pragma GCC diagnostic warning "-Wunused-local-typedefs" # endif #endif diff --git a/src/io/parser/parser_random.cc b/src/io/parser/parser_random.cc index c17d43714..1afe8d60b 100644 --- a/src/io/parser/parser_random.cc +++ b/src/io/parser/parser_random.cc @@ -1,69 +1,69 @@ /** * @file parser_random.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Mon Dec 07 2015 * * @brief implementation of the parser * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #if defined(__INTEL_COMPILER) //#pragma warning ( disable : 383 ) #elif defined (__clang__) // test clang to be sure that when we test for gnu it is only gnu #elif (defined(__GNUC__) || defined(__GNUG__)) # define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) # if GCC_VERSION > 40600 # pragma GCC diagnostic push # endif # pragma GCC diagnostic ignored "-Wunused-local-typedefs" #endif /* -------------------------------------------------------------------------- */ #include "parser.hh" #include "parser_grammar_tmpl.hh" /* -------------------------------------------------------------------------- */ #include "algebraic_parser.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ RandomParameter<Real> Parser::parseRandomParameter(const std::string & value, const ParserSection & section) { using boost::spirit::ascii::space_type; parser::RandomGeneratorGrammar<std::string::const_iterator, space_type> grammar(section); grammar.name("random_grammar"); parser::ParsableRandomGenerator rg = Parser::parseType<parser::ParsableRandomGenerator>(value, grammar); Vector<Real> params = rg.parameters; switch(rg.type) { case _rdt_not_defined: return RandomParameter<Real>(rg.base); case _rdt_uniform: return RandomParameter<Real>(rg.base, UniformDistribution<Real>(params(0), params(1))); case _rdt_weibull: return RandomParameter<Real>(rg.base, WeibullDistribution<Real>(params(0), params(1))); default: AKANTU_EXCEPTION("This is an unknown random distribution in the parser"); } } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/io/parser/parser_real.cc b/src/io/parser/parser_real.cc index accd1ff36..c232530fd 100644 --- a/src/io/parser/parser_real.cc +++ b/src/io/parser/parser_real.cc @@ -1,59 +1,59 @@ /** * @file parser_real.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Wed Nov 11 2015 * * @brief implementation of the parser * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #if defined(__INTEL_COMPILER) //#pragma warning ( disable : 383 ) #elif defined (__clang__) // test clang to be sure that when we test for gnu it is only gnu #elif (defined(__GNUC__) || defined(__GNUG__)) # define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) # if GCC_VERSION > 40600 # pragma GCC diagnostic push # endif # pragma GCC diagnostic ignored "-Wunused-local-typedefs" #endif /* -------------------------------------------------------------------------- */ #include "parser.hh" #include "parser_grammar_tmpl.hh" /* -------------------------------------------------------------------------- */ #include "algebraic_parser.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ Real Parser::parseReal(const std::string & value, const ParserSection & section) { using boost::spirit::ascii::space_type; parser::AlgebraicGrammar<std::string::const_iterator, space_type> grammar(section); grammar.name("algebraic_grammar"); return Parser::parseType<Real>(value, grammar); } -__END_AKANTU__ +} // akantu diff --git a/src/io/parser/parser_tmpl.hh b/src/io/parser/parser_tmpl.hh index 336ffef75..7463032be 100644 --- a/src/io/parser/parser_tmpl.hh +++ b/src/io/parser/parser_tmpl.hh @@ -1,106 +1,106 @@ /** * @file parser_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Wed Apr 22 2015 * * @brief Implementation of the parser templated methods * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <typename T> inline ParserParameter::operator T() const { T t; std::stringstream sstr(value); sstr >> t; if(sstr.bad()) AKANTU_EXCEPTION("No known conversion of a ParserParameter \"" << name << "\" to the type " << typeid(T).name()); return t; } /* -------------------------------------------------------------------------- */ template<> inline ParserParameter::operator const char *() const { return value.c_str(); } /* -------------------------------------------------------------------------- */ template<> inline ParserParameter::operator Real() const { return Parser::parseReal(value, *parent_section); } /* --------------------------------------------------------- ----------------- */ template<> inline ParserParameter::operator bool() const { bool b; std::stringstream sstr(value); sstr >> std::boolalpha >> b; if(sstr.fail()) { sstr.clear(); sstr >> std::noboolalpha >> b; } return b; } /* --------------------------------------------------------- ----------------- */ template<> inline ParserParameter::operator Vector<Real>() const { return Parser::parseVector(value, *parent_section); } /* --------------------------------------------------------- ----------------- */ template<> inline ParserParameter::operator Vector<UInt>() const { Vector<Real> tmp = Parser::parseVector(value, *parent_section); Vector<UInt> tmp_uint(tmp.size()); for (UInt i=0; i<tmp.size(); ++i) { tmp_uint(i) = UInt(tmp(i)); } return tmp_uint; } /* --------------------------------------------------------- ----------------- */ template<> inline ParserParameter::operator Matrix<Real>() const { return Parser::parseMatrix(value, *parent_section); } /* -------------------------------------------------------------------------- */ template<> inline ParserParameter::operator RandomParameter<Real>() const { return Parser::parseRandomParameter(value, *parent_section); } -__END_AKANTU__ +} // akantu diff --git a/src/io/parser/parser_types.cc b/src/io/parser/parser_types.cc index a30bcf903..ff6565216 100644 --- a/src/io/parser/parser_types.cc +++ b/src/io/parser/parser_types.cc @@ -1,69 +1,69 @@ /** * @file parser_types.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Wed Nov 11 2015 * * @brief implementation of the parser * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #if defined(__INTEL_COMPILER) //#pragma warning ( disable : 383 ) #elif defined (__clang__) // test clang to be sure that when we test for gnu it is only gnu #elif (defined(__GNUC__) || defined(__GNUG__)) # define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) # if GCC_VERSION > 40600 # pragma GCC diagnostic push # endif # pragma GCC diagnostic ignored "-Wunused-local-typedefs" #endif /* -------------------------------------------------------------------------- */ #include "parser.hh" #include "parser_grammar_tmpl.hh" /* -------------------------------------------------------------------------- */ #include "algebraic_parser.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ Vector<Real> Parser::parseVector(const std::string & value, const ParserSection & section) { using boost::spirit::ascii::space_type; parser::VectorGrammar<std::string::const_iterator, space_type> grammar(section); grammar.name("vector_grammar"); return Parser::parseType<parser::parsable_vector>(value, grammar); } /* -------------------------------------------------------------------------- */ Matrix<Real> Parser::parseMatrix(const std::string & value, const ParserSection & section) { using boost::spirit::ascii::space_type; parser::MatrixGrammar<std::string::const_iterator, space_type> grammar(section); grammar.name("matrix_grammar"); return Parser::parseType<parser::parsable_matrix>(value, grammar); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/mesh/element_group.cc b/src/mesh/element_group.cc index 24bf91037..591a66141 100644 --- a/src/mesh/element_group.cc +++ b/src/mesh/element_group.cc @@ -1,201 +1,201 @@ /** * @file element_group.cc * * @author Dana Christen <dana.christen@gmail.com> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Tue Aug 18 2015 * * @brief Stores information relevent to the notion of domain boundary and surfaces. * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <sstream> #include <algorithm> #include <iterator> #include "mesh.hh" #include "group_manager.hh" #include "group_manager_inline_impl.cc" #include "dumpable.hh" #include "dumpable_inline_impl.hh" #include "aka_csr.hh" #include "mesh_utils.hh" #include "element_group.hh" #if defined(AKANTU_USE_IOHELPER) # include "dumper_paraview.hh" #endif -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ ElementGroup::ElementGroup(const std::string & group_name, const Mesh & mesh, NodeGroup & node_group, UInt dimension, const std::string & id, const MemoryID & mem_id) : Memory(id, mem_id), mesh(mesh), name(group_name), elements("elements", id, mem_id), node_group(node_group), dimension(dimension) { AKANTU_DEBUG_IN(); #if defined(AKANTU_USE_IOHELPER) this->registerDumper<DumperParaview>("paraview_" + group_name, group_name, true); this->addDumpFilteredMesh(mesh, elements, node_group.getNodes(), dimension); #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ElementGroup::empty() { elements.free(); } /* -------------------------------------------------------------------------- */ void ElementGroup::append(const ElementGroup & other_group) { AKANTU_DEBUG_IN(); node_group.append(other_group.node_group); /// loop on all element types in all dimensions for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; type_iterator it = other_group.firstType(_all_dimensions, ghost_type, _ek_not_defined); type_iterator last = other_group.lastType(_all_dimensions, ghost_type, _ek_not_defined); for (; it != last; ++it) { ElementType type = *it; const Array<UInt> & other_elem_list = other_group.elements(type, ghost_type); UInt nb_other_elem = other_elem_list.getSize(); Array<UInt> * elem_list; UInt nb_elem = 0; /// create current type if doesn't exists, otherwise get information if (elements.exists(type, ghost_type)) { elem_list = &elements(type, ghost_type); nb_elem = elem_list->getSize(); } else { elem_list = &(elements.alloc(0, 1, type, ghost_type)); } /// append new elements to current list elem_list->resize(nb_elem + nb_other_elem); std::copy(other_elem_list.begin(), other_elem_list.end(), elem_list->begin() + nb_elem); /// remove duplicates std::sort(elem_list->begin(), elem_list->end()); Array<UInt>::iterator<> end = std::unique(elem_list->begin(), elem_list->end()); elem_list->resize(end - elem_list->begin()); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ElementGroup::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "ElementGroup [" << std::endl; stream << space << " + name: " << name << std::endl; stream << space << " + dimension: " << dimension << std::endl; elements.printself(stream, indent + 1); node_group.printself(stream, indent + 1); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ void ElementGroup::optimize() { // increasing the locality of data when iterating on the element of a group for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; ElementList::type_iterator it = elements.firstType(_all_dimensions, ghost_type); ElementList::type_iterator last = elements.lastType(_all_dimensions, ghost_type); for (; it != last; ++it) { Array<UInt> & els = elements(*it, ghost_type); std::sort(els.begin(), els.end()); Array<UInt>::iterator<> end = std::unique(els.begin(), els.end()); els.resize(end - els.begin()); } } node_group.optimize(); } /* -------------------------------------------------------------------------- */ void ElementGroup::fillFromNodeGroup() { CSR<Element> node_to_elem; MeshUtils::buildNode2Elements(this->mesh, node_to_elem, this->dimension); std::set<Element> seen; Array<UInt>::const_iterator<> itn = this->node_group.begin(); Array<UInt>::const_iterator<> endn = this->node_group.end(); for (;itn != endn; ++itn) { CSR<Element>::iterator ite = node_to_elem.begin(*itn); CSR<Element>::iterator ende = node_to_elem.end(*itn); for (;ite != ende; ++ite) { const Element & elem = *ite; if(this->dimension != _all_dimensions && this->dimension != Mesh::getSpatialDimension(elem.type)) continue; if(seen.find(elem) != seen.end()) continue; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(elem.type); Array<UInt>::const_iterator< Vector<UInt> > conn_it = this->mesh.getConnectivity(elem.type, elem.ghost_type).begin(nb_nodes_per_element); const Vector<UInt> & conn = conn_it[elem.element]; UInt count = 0; for (UInt n = 0; n < conn.size(); ++n) { count += (this->node_group.getNodes().find(conn(n)) != -1 ? 1 : 0); } if(count == nb_nodes_per_element) this->add(elem); seen.insert(elem); } } this->optimize(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/mesh/element_group.hh b/src/mesh/element_group.hh index 895b9e745..be5a6ab5c 100644 --- a/src/mesh/element_group.hh +++ b/src/mesh/element_group.hh @@ -1,188 +1,188 @@ /** * @file element_group.hh * * @author Dana Christen <dana.christen@gmail.com> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri May 03 2013 * @date last modification: Tue Aug 18 2015 * * @brief Stores information relevent to the notion of domain boundary and * surfaces. * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "dumpable.hh" #include "element_type_map.hh" #include "node_group.hh" /* -------------------------------------------------------------------------- */ #include <set> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ELEMENT_GROUP_HH__ #define __AKANTU_ELEMENT_GROUP_HH__ namespace akantu { class Mesh; class Element; } // akantu -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ class ElementGroup : private Memory, public Dumpable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ElementGroup(const std::string & name, const Mesh & mesh, NodeGroup & node_group, UInt dimension = _all_dimensions, const std::string & id = "element_group", const MemoryID & memory_id = 0); /* ------------------------------------------------------------------------ */ /* Type definitions */ /* ------------------------------------------------------------------------ */ public: typedef ElementTypeMapArray<UInt> ElementList; typedef Array<UInt> NodeList; /* ------------------------------------------------------------------------ */ /* Node iterator */ /* ------------------------------------------------------------------------ */ typedef NodeGroup::const_node_iterator const_node_iterator; inline const_node_iterator node_begin() const; inline const_node_iterator node_end() const; /* ------------------------------------------------------------------------ */ /* Element iterator */ /* ------------------------------------------------------------------------ */ typedef ElementList::type_iterator type_iterator; inline type_iterator firstType(UInt dim = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & kind = _ek_regular) const; inline type_iterator lastType(UInt dim = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & kind = _ek_regular) const; typedef Array<UInt>::const_iterator<UInt> const_element_iterator; inline const_element_iterator element_begin(const ElementType & type, const GhostType & ghost_type = _not_ghost) const; inline const_element_iterator element_end(const ElementType & type, const GhostType & ghost_type = _not_ghost) const; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// empty the element group void empty(); /// append another group to this group /// BE CAREFUL: it doesn't conserve the element order void append(const ElementGroup & other_group); /// add an element to the group. By default the it does not add the nodes to /// the group inline void add(const Element & el, bool add_nodes = false, bool check_for_duplicate = true); /// \todo fix the default for add_nodes : make it coherent with the other /// method inline void add(const ElementType & type, UInt element, const GhostType & ghost_type = _not_ghost, bool add_nodes = true, bool check_for_duplicate = true); inline void addNode(UInt node_id, bool check_for_duplicate = true); inline void removeNode(UInt node_id); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /// fill the elements based on the underlying node group. virtual void fillFromNodeGroup(); // sort and remove duplicated values void optimize(); private: inline void addElement(const ElementType & elem_type, UInt elem_id, const GhostType & ghost_type); friend class GroupManager; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Elements, elements, UInt); AKANTU_GET_MACRO(Elements, elements, const ElementTypeMapArray<UInt> &); AKANTU_GET_MACRO(Nodes, node_group.getNodes(), const Array<UInt> &); AKANTU_GET_MACRO(NodeGroup, node_group, const NodeGroup &); AKANTU_GET_MACRO_NOT_CONST(NodeGroup, node_group, NodeGroup &); AKANTU_GET_MACRO(Dimension, dimension, UInt); AKANTU_GET_MACRO(Name, name, std::string); inline UInt getNbNodes() const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// Mesh to which this group belongs const Mesh & mesh; /// name of the group std::string name; /// list of elements composing the group ElementList elements; /// sub list of nodes which are composing the elements NodeGroup & node_group; /// group dimension UInt dimension; /// empty arry for the iterator to work when an element type not present Array<UInt> empty_elements; }; /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const ElementGroup & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #include "element.hh" #include "element_group_inline_impl.cc" #endif /* __AKANTU_ELEMENT_GROUP_HH__ */ diff --git a/src/mesh/element_group_inline_impl.cc b/src/mesh/element_group_inline_impl.cc index d6047bf81..ba16ea036 100644 --- a/src/mesh/element_group_inline_impl.cc +++ b/src/mesh/element_group_inline_impl.cc @@ -1,137 +1,137 @@ /** * @file element_group_inline_impl.cc * * @author Dana Christen <dana.christen@gmail.com> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Tue Aug 18 2015 * * @brief Stores information relevent to the notion of domain boundary and * surfaces. * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "mesh.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ inline void ElementGroup::add(const Element & el, bool add_nodes, bool check_for_duplicate) { this->add(el.type,el.element,el.ghost_type,add_nodes,check_for_duplicate); } /* -------------------------------------------------------------------------- */ inline void ElementGroup::add(const ElementType & type, UInt element, const GhostType & ghost_type,bool add_nodes, bool check_for_duplicate) { addElement(type, element, ghost_type); if(add_nodes) { Array<UInt>::const_vector_iterator it = mesh.getConnectivity(type, ghost_type).begin(mesh.getNbNodesPerElement(type)) + element; const Vector<UInt> & conn = *it; for (UInt i = 0; i < conn.size(); ++i) addNode(conn[i], check_for_duplicate); } } /* -------------------------------------------------------------------------- */ inline void ElementGroup::addNode(UInt node_id, bool check_for_duplicate) { node_group.add(node_id, check_for_duplicate); } /* -------------------------------------------------------------------------- */ inline void ElementGroup::removeNode(UInt node_id) { node_group.remove(node_id); } /* -------------------------------------------------------------------------- */ inline void ElementGroup::addElement(const ElementType & elem_type, UInt elem_id, const GhostType & ghost_type) { if(!(elements.exists(elem_type, ghost_type))) { elements.alloc(0, 1, elem_type, ghost_type); } elements(elem_type, ghost_type).push_back(elem_id); this->dimension = UInt(std::max(Int(this->dimension), Int(mesh.getSpatialDimension(elem_type)))); } /* -------------------------------------------------------------------------- */ inline UInt ElementGroup::getNbNodes() const { return node_group.getSize(); } /* -------------------------------------------------------------------------- */ inline ElementGroup::const_node_iterator ElementGroup::node_begin() const { return node_group.begin(); } /* -------------------------------------------------------------------------- */ inline ElementGroup::const_node_iterator ElementGroup::node_end() const { return node_group.end(); } /* -------------------------------------------------------------------------- */ inline ElementGroup::type_iterator ElementGroup::firstType(UInt dim, const GhostType & ghost_type, const ElementKind & kind) const { return elements.firstType(dim, ghost_type, kind); } /* -------------------------------------------------------------------------- */ inline ElementGroup::type_iterator ElementGroup::lastType(UInt dim, const GhostType & ghost_type, const ElementKind & kind) const { return elements.lastType(dim, ghost_type, kind); } /* -------------------------------------------------------------------------- */ inline ElementGroup::const_element_iterator ElementGroup::element_begin(const ElementType & type, const GhostType & ghost_type) const { if(elements.exists(type, ghost_type)) { return elements(type, ghost_type).begin(); } else { return empty_elements.begin(); } } /* -------------------------------------------------------------------------- */ inline ElementGroup::const_element_iterator ElementGroup::element_end(const ElementType & type, const GhostType & ghost_type) const { if(elements.exists(type, ghost_type)) { return elements(type, ghost_type).end(); } else { return empty_elements.end(); } } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/mesh/element_type_map.hh b/src/mesh/element_type_map.hh index 348d1940f..f005c409a 100644 --- a/src/mesh/element_type_map.hh +++ b/src/mesh/element_type_map.hh @@ -1,368 +1,368 @@ /** * @file element_type_map.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Aug 31 2011 * @date last modification: Fri Oct 02 2015 * * @brief storage class by element type * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ELEMENT_TYPE_MAP_HH__ #define __AKANTU_ELEMENT_TYPE_MAP_HH__ #include "aka_array.hh" #include "aka_common.hh" #include "aka_memory.hh" -__BEGIN_AKANTU__ +namespace akantu { template <class Stored, typename SupportType = ElementType> class ElementTypeMap; /* -------------------------------------------------------------------------- */ /* ElementTypeMapBase */ /* -------------------------------------------------------------------------- */ /// Common non templated base class for the ElementTypeMap class class ElementTypeMapBase { public: virtual ~ElementTypeMapBase(){}; }; /* -------------------------------------------------------------------------- */ /* ElementTypeMap */ /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> class ElementTypeMap : public ElementTypeMapBase { public: ElementTypeMap(); ~ElementTypeMap(); inline static std::string printType(const SupportType & type, const GhostType & ghost_type); /*! Tests whether a type is present in the object * @param type the type to check for * @param ghost_type optional: by default, the data map for non-ghost * elements is searched * @return true if the type is present. */ inline bool exists(const SupportType & type, const GhostType & ghost_type = _not_ghost) const; /*! get the stored data corresponding to a type * @param type the type to check for * @param ghost_type optional: by default, the data map for non-ghost * elements is searched * @return stored data corresponding to type. */ inline const Stored & operator()(const SupportType & type, const GhostType & ghost_type = _not_ghost) const; /*! get the stored data corresponding to a type * @param type the type to check for * @param ghost_type optional: by default, the data map for non-ghost * elements is searched * @return stored data corresponding to type. */ inline Stored & operator()(const SupportType & type, const GhostType & ghost_type = _not_ghost); /*! insert data of a new type (not yet present) into the map. THIS METHOD IS * NOT ARRAY SAFE, when using ElementTypeMapArray, use setArray instead * @param data to insert * @param type type of data (if this type is already present in the map, * an exception is thrown). * @param ghost_type optional: by default, the data map for non-ghost * elements is searched * @return stored data corresponding to type. */ inline Stored & operator()(const Stored & insert, const SupportType & type, const GhostType & ghost_type = _not_ghost); /// print helper virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Element type Iterator */ /* ------------------------------------------------------------------------ */ /*! iterator allows to iterate over type-data pairs of the map. The interface * expects the SupportType to be ElementType. */ typedef std::map<SupportType, Stored> DataMap; class type_iterator : private std::iterator<std::forward_iterator_tag, const SupportType> { public: typedef const SupportType value_type; typedef const SupportType * pointer; typedef const SupportType & reference; protected: typedef typename ElementTypeMap<Stored>::DataMap::const_iterator DataMapIterator; public: type_iterator(DataMapIterator & list_begin, DataMapIterator & list_end, UInt dim, ElementKind ek); type_iterator(const type_iterator & it); type_iterator() {} inline reference operator*(); inline reference operator*() const; inline type_iterator & operator++(); type_iterator operator++(int); inline bool operator==(const type_iterator & other) const; inline bool operator!=(const type_iterator & other) const; type_iterator & operator=(const type_iterator & other); private: DataMapIterator list_begin; DataMapIterator list_end; UInt dim; ElementKind kind; }; /// helper class to use in range for constructions class ElementTypesIteratorHelper { public: using Container = ElementTypeMap<Stored, SupportType>; using iterator = typename Container::type_iterator; ElementTypesIteratorHelper(const Container & container, UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_regular) : container(std::cref(container)), dim(dim), ghost_type(ghost_type), kind(kind) {} ElementTypesIteratorHelper(const ElementTypesIteratorHelper &) = default; ElementTypesIteratorHelper & operator=(const ElementTypesIteratorHelper &) = default; ElementTypesIteratorHelper & operator=(ElementTypesIteratorHelper &&) = default; iterator begin() { return container.get().firstType(dim, ghost_type, kind); } iterator end() { return container.get().lastType(dim, ghost_type, kind); } private: std::reference_wrapper<const Container> container; UInt dim; GhostType ghost_type; ElementKind kind; }; /// method to create the helper class to use in range for constructs ElementTypesIteratorHelper elementTypes(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_regular) const; /*! Get an iterator to the beginning of a subset datamap. This method expects * the SupportType to be ElementType. * @param dim optional: iterate over data of dimension dim (e.g. when * iterating over (surface) facets of a 3D mesh, dim would be 2). * by default, all dimensions are considered. * @param ghost_type optional: by default, the data map for non-ghost * elements is iterated over. * @param kind optional: the kind of element to search for (see * aka_common.hh), by default all kinds are considered * @return an iterator to the first stored data matching the filters * or an iterator to the end of the map if none match*/ inline type_iterator firstType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_not_defined) const; /*! Get an iterator to the end of a subset datamap. This method expects * the SupportType to be ElementType. * @param dim optional: iterate over data of dimension dim (e.g. when * iterating over (surface) facets of a 3D mesh, dim would be 2). * by default, all dimensions are considered. * @param ghost_type optional: by default, the data map for non-ghost * elements is iterated over. * @param kind optional: the kind of element to search for (see * aka_common.hh), by default all kinds are considered * @return an iterator to the last stored data matching the filters * or an iterator to the end of the map if none match */ inline type_iterator lastType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_not_defined) const; protected: /*! Direct access to the underlying data map. for internal use by daughter * classes only * @param ghost_type whether to return the data map or the ghost_data map * @return the raw map */ inline DataMap & getData(GhostType ghost_type); /*! Direct access to the underlying data map. for internal use by daughter * classes only * @param ghost_type whether to return the data map or the ghost_data map * @return the raw map */ inline const DataMap & getData(GhostType ghost_type) const; /* ------------------------------------------------------------------------ */ protected: DataMap data; DataMap ghost_data; }; /* -------------------------------------------------------------------------- */ /* Some typedefs */ /* -------------------------------------------------------------------------- */ template <typename T, typename SupportType> class ElementTypeMapArray : public ElementTypeMap<Array<T> *, SupportType>, public Memory { public: typedef T type; typedef Array<T> array_type; protected: typedef ElementTypeMap<Array<T> *, SupportType> parent; typedef typename parent::DataMap DataMap; private: private: /// standard assigment (copy) operator void operator=(const ElementTypeMap<T, SupportType> &){}; public: typedef typename parent::type_iterator type_iterator; /*! Constructor * @param id optional: identifier (string) * @param parent_id optional: parent identifier. for organizational purposes * only * @param memory_id optional: choose a specific memory, defaults to memory 0 */ ElementTypeMapArray(const ID & id = "by_element_type_array", const ID & parent_id = "no_parent", const MemoryID & memory_id = 0) : parent(), Memory(parent_id + ":" + id, memory_id), name(id){}; /*! allocate memory for a new array * @param size number of tuples of the new array * @param nb_component tuple size * @param type the type under which the array is indexed in the map * @param ghost_type whether to add the field to the data map or the * ghost_data map * @return a reference to the allocated array */ inline Array<T> & alloc(UInt size, UInt nb_component, const SupportType & type, const GhostType & ghost_type, const T & default_value = T()); /*! allocate memory for a new array in both the data and the ghost_data map * @param size number of tuples of the new array * @param nb_component tuple size * @param type the type under which the array is indexed in the map*/ inline void alloc(UInt size, UInt nb_component, const SupportType & type, const T & default_value = T()); /* get a reference to the array of certain type * @param type data filed under type is returned * @param ghost_type optional: by default the non-ghost map is searched * @return a reference to the array */ inline const Array<T> & operator()(const SupportType & type, const GhostType & ghost_type = _not_ghost) const; /* get a reference to the array of certain type * @param type data filed under type is returned * @param ghost_type optional: by default the non-ghost map is searched * @return a const reference to the array */ inline Array<T> & operator()(const SupportType & type, const GhostType & ghost_type = _not_ghost); /*! insert data of a new type (not yet present) into the map. * @param type type of data (if this type is already present in the map, * an exception is thrown). * @param ghost_type optional: by default, the data map for non-ghost * elements is searched * @param vect the vector to include into the map * @return stored data corresponding to type. */ inline void setArray(const SupportType & type, const GhostType & ghost_type, const Array<T> & vect); /*! frees all memory related to the data*/ inline void free(); /*! set all values in the ElementTypeMap to zero*/ inline void clear(); /*! deletes and reorders entries in the stored arrays * @param new_numbering a ElementTypeMapArray of new indices. UInt(-1) * indicates * deleted entries. */ inline void onElementsRemoved(const ElementTypeMapArray<UInt> & new_numbering); /// text output helper virtual void printself(std::ostream & stream, int indent = 0) const; /*! set the id * @param id the new name */ inline void setID(const ID & id) { this->id = id; } ElementTypeMap<UInt> getNbComponents(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_not_defined) const { ElementTypeMap<UInt> nb_components; type_iterator tit = this->firstType(dim, ghost_type, kind); type_iterator end = this->lastType(dim, ghost_type, kind); while (tit != end) { UInt nb_comp = (*this)(*tit, ghost_type).getNbComponent(); nb_components(*tit, ghost_type) = nb_comp; ++tit; } return nb_components; } /* -------------------------------------------------------------------------- */ /* Accesssors */ /* -------------------------------------------------------------------------- */ public: /// get the name of the internal field AKANTU_GET_MACRO(Name, name, ID); private: ElementTypeMapArray operator=(__attribute__((unused)) const ElementTypeMapArray & other){}; /// name of the elment type map: e.g. connectivity, grad_u ID name; }; /// to store data Array<Real> by element type typedef ElementTypeMapArray<Real> ElementTypeMapReal; /// to store data Array<Int> by element type typedef ElementTypeMapArray<Int> ElementTypeMapInt; /// to store data Array<UInt> by element type typedef ElementTypeMapArray<UInt, ElementType> ElementTypeMapUInt; /// Map of data of type UInt stored in a mesh typedef std::map<std::string, Array<UInt> *> UIntDataMap; typedef ElementTypeMap<UIntDataMap, ElementType> ElementTypeMapUIntDataMap; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_ELEMENT_TYPE_MAP_HH__ */ diff --git a/src/mesh/element_type_map_filter.hh b/src/mesh/element_type_map_filter.hh index 32011621b..99b94ae06 100644 --- a/src/mesh/element_type_map_filter.hh +++ b/src/mesh/element_type_map_filter.hh @@ -1,335 +1,335 @@ /** * @file element_type_map_filter.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Sep 02 2014 * @date last modification: Fri Dec 18 2015 * * @brief Filtered version based on a an akantu::ElementGroup of a * akantu::ElementTypeMap * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_BY_ELEMENT_TYPE_FILTER_HH__ #define __AKANTU_BY_ELEMENT_TYPE_FILTER_HH__ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* ArrayFilter */ /* -------------------------------------------------------------------------- */ template <typename T> class ArrayFilter { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: /// standard iterator template <typename R = T> class iterator { inline bool operator!=(__attribute__((unused)) iterator<R> & other) { throw; }; inline bool operator==(__attribute__((unused)) iterator<R> & other) { throw; }; inline iterator<R> & operator++() { throw; }; inline T operator*() { throw; return T(); }; }; /// const iterator template <template <class S> class original_iterator, typename Shape, typename filter_iterator> class const_iterator { public: UInt getCurrentIndex() { return (*this->filter_it * this->nb_item_per_elem + this->sub_element_counter); } inline const_iterator(){}; inline const_iterator(const original_iterator<Shape> & origin_it, const filter_iterator & filter_it, UInt nb_item_per_elem) : origin_it(origin_it), filter_it(filter_it), nb_item_per_elem(nb_item_per_elem), sub_element_counter(0){}; inline bool operator!=(const_iterator & other) const { return !((*this) == other); } inline bool operator==(const_iterator & other) const { return (this->origin_it == other.origin_it && this->filter_it == other.filter_it && this->sub_element_counter == other.sub_element_counter); } inline bool operator!=(const const_iterator & other) const { return !((*this) == other); } inline bool operator==(const const_iterator & other) const { return (this->origin_it == other.origin_it && this->filter_it == other.filter_it && this->sub_element_counter == other.sub_element_counter); } inline const_iterator & operator++() { ++sub_element_counter; if (sub_element_counter == nb_item_per_elem) { sub_element_counter = 0; ++filter_it; } return *this; }; inline Shape operator*() { return origin_it[nb_item_per_elem * (*filter_it) + sub_element_counter]; }; private: original_iterator<Shape> origin_it; filter_iterator filter_it; /// the number of item per element UInt nb_item_per_elem; /// counter for every sub element group UInt sub_element_counter; }; typedef iterator<Vector<T> > vector_iterator; typedef Array<T> array_type; typedef const_iterator<array_type::template const_iterator, Vector<T>, Array<UInt>::const_iterator<UInt> > const_vector_iterator; typedef typename array_type::value_type value_type; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ArrayFilter(const Array<T> & array, const Array<UInt> & filter, UInt nb_item_per_elem) : array(array), filter(filter), nb_item_per_elem(nb_item_per_elem){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ const_vector_iterator begin_reinterpret(UInt n, UInt new_size) const { AKANTU_DEBUG_ASSERT( n * new_size == this->getNbComponent() * this->getSize(), "The new values for size (" << new_size << ") and nb_component (" << n << ") are not compatible with the one of this array(" << this->getSize() << "," << this->getNbComponent() << ")"); UInt new_full_array_size = this->array.getSize() * array.getNbComponent() / n; UInt new_nb_item_per_elem = this->nb_item_per_elem; if (new_size != 0 && n != 0) new_nb_item_per_elem = this->array.getNbComponent() * this->filter.getSize() * this->nb_item_per_elem / (n * new_size); return const_vector_iterator( this->array.begin_reinterpret(n, new_full_array_size), this->filter.begin(), new_nb_item_per_elem); }; const_vector_iterator end_reinterpret(UInt n, UInt new_size) const { AKANTU_DEBUG_ASSERT( n * new_size == this->getNbComponent() * this->getSize(), "The new values for size (" << new_size << ") and nb_component (" << n << ") are not compatible with the one of this array(" << this->getSize() << "," << this->getNbComponent() << ")"); UInt new_full_array_size = this->array.getSize() * this->array.getNbComponent() / n; UInt new_nb_item_per_elem = this->nb_item_per_elem; if (new_size != 0 && n != 0) new_nb_item_per_elem = this->array.getNbComponent() * this->filter.getSize() * this->nb_item_per_elem / (n * new_size); return const_vector_iterator( this->array.begin_reinterpret(n, new_full_array_size), this->filter.end(), new_nb_item_per_elem); }; vector_iterator begin_reinterpret(UInt, UInt) { throw; }; vector_iterator end_reinterpret(UInt, UInt) { throw; }; /// return the size of the filtered array which is the filter size UInt getSize() const { return this->filter.getSize() * this->nb_item_per_elem; }; /// the number of components of the filtered array UInt getNbComponent() const { return this->array.getNbComponent(); }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// reference to array of data const Array<T> & array; /// reference to the filter used to select elements const Array<UInt> & filter; /// the number of item per element UInt nb_item_per_elem; }; /* -------------------------------------------------------------------------- */ /* ElementTypeMapFilter */ /* -------------------------------------------------------------------------- */ template <class T, typename SupportType = ElementType> class ElementTypeMapArrayFilter { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: typedef T type; typedef ArrayFilter<T> array_type; typedef typename array_type::value_type value_type; typedef typename ElementTypeMapArray<UInt, SupportType>::type_iterator type_iterator; // class type_iterator{ // public: // typedef typename ElementTypeMapArray<T,SupportType>::type_iterator // type_it; // public: // type_iterator(){}; // // type_iterator(const type_iterator & it){original_it = // it.original_it;}; // type_iterator(const type_it & it){original_it = it;}; // inline ElementType & operator*(){throw;}; // inline ElementType & operator*() const{throw;}; // inline type_iterator & operator++(){throw;return *this;}; // type_iterator operator++(int){throw; return *this;}; // inline bool operator==(const type_iterator & other) const{throw;return // false;}; // inline bool operator!=(const type_iterator & other) const{throw;return // false;}; // // type_iterator & operator=(const type_iterator & other){throw;return // *this;}; // type_it original_it; // }; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ElementTypeMapArrayFilter( const ElementTypeMapArray<T, SupportType> & array, const ElementTypeMapArray<UInt, SupportType> & filter, const ElementTypeMap<UInt, SupportType> & nb_data_per_elem) : array(array), filter(filter), nb_data_per_elem(nb_data_per_elem) {} ElementTypeMapArrayFilter( const ElementTypeMapArray<T, SupportType> & array, const ElementTypeMapArray<UInt, SupportType> & filter) : array(array), filter(filter) {} ~ElementTypeMapArrayFilter() {} /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ inline const ArrayFilter<T> operator()(const SupportType & type, const GhostType & ghost_type = _not_ghost) const { if (filter.exists(type, ghost_type)) { if (nb_data_per_elem.exists(type, ghost_type)) return ArrayFilter<T>(array(type, ghost_type), filter(type, ghost_type), nb_data_per_elem(type, ghost_type) / array(type, ghost_type).getNbComponent()); else return ArrayFilter<T>(array(type, ghost_type), filter(type, ghost_type), 1); } else { return ArrayFilter<T>(empty_array, empty_filter, 1); } }; inline type_iterator firstType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_not_defined) const { return filter.firstType(dim, ghost_type, kind); }; inline type_iterator lastType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_not_defined) const { return filter.lastType(dim, ghost_type, kind); }; ElementTypeMap<UInt> getNbComponents(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_not_defined) const { return this->array.getNbComponents(dim, ghost_type, kind); }; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ std::string getID() { return std::string("filtered:" + this->array().getID()); } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: const ElementTypeMapArray<T, SupportType> & array; const ElementTypeMapArray<UInt, SupportType> & filter; ElementTypeMap<UInt> nb_data_per_elem; /// Empty array to be able to return consistent filtered arrays Array<T> empty_array; Array<UInt> empty_filter; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_BY_ELEMENT_TYPE_FILTER_HH__ */ diff --git a/src/mesh/group_manager.cc b/src/mesh/group_manager.cc index 5e2fa9a07..536964d94 100644 --- a/src/mesh/group_manager.cc +++ b/src/mesh/group_manager.cc @@ -1,1028 +1,1028 @@ /** * @file group_manager.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Dana Christen <dana.christen@gmail.com> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Mon Aug 17 2015 * * @brief Stores information about ElementGroup and NodeGroup * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "group_manager.hh" #include "aka_csr.hh" #include "mesh.hh" #include "mesh_utils.hh" #include "data_accessor.hh" #include "element_synchronizer.hh" #include "element_group.hh" #include "node_group.hh" /* -------------------------------------------------------------------------- */ #include <algorithm> #include <iterator> #include <list> #include <numeric> #include <queue> #include <sstream> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ GroupManager::GroupManager(const Mesh & mesh, const ID & id, const MemoryID & mem_id) : id(id), memory_id(mem_id), mesh(mesh) { AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ GroupManager::~GroupManager() { ElementGroups::iterator eit = element_groups.begin(); ElementGroups::iterator eend = element_groups.end(); for (; eit != eend; ++eit) delete (eit->second); NodeGroups::iterator nit = node_groups.begin(); NodeGroups::iterator nend = node_groups.end(); for (; nit != nend; ++nit) delete (nit->second); } /* -------------------------------------------------------------------------- */ NodeGroup & GroupManager::createNodeGroup(const std::string & group_name, bool replace_group) { AKANTU_DEBUG_IN(); NodeGroups::iterator it = node_groups.find(group_name); if (it != node_groups.end()) { if (replace_group) { it->second->empty(); AKANTU_DEBUG_OUT(); return *(it->second); } else AKANTU_EXCEPTION( "Trying to create a node group that already exists:" << group_name); } std::stringstream sstr; sstr << this->id << ":" << group_name << "_node_group"; NodeGroup * node_group = new NodeGroup(group_name, mesh, sstr.str(), memory_id); node_groups[group_name] = node_group; AKANTU_DEBUG_OUT(); return *node_group; } /* -------------------------------------------------------------------------- */ template <typename T> NodeGroup & GroupManager::createFilteredNodeGroup(const std::string & group_name, const NodeGroup & source_node_group, T & filter) { AKANTU_DEBUG_IN(); NodeGroup & node_group = this->createNodeGroup(group_name); node_group.append(source_node_group); if (T::type == FilterFunctor::_node_filter_functor) { node_group.applyNodeFilter(filter); } else { AKANTU_DEBUG_ERROR("ElementFilter cannot be applied to NodeGroup yet." << " Needs to be implemented."); } AKANTU_DEBUG_OUT(); return node_group; } /* -------------------------------------------------------------------------- */ void GroupManager::destroyNodeGroup(const std::string & group_name) { AKANTU_DEBUG_IN(); NodeGroups::iterator nit = node_groups.find(group_name); NodeGroups::iterator nend = node_groups.end(); if (nit != nend) { delete (nit->second); node_groups.erase(nit); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ElementGroup & GroupManager::createElementGroup(const std::string & group_name, UInt dimension, bool replace_group) { AKANTU_DEBUG_IN(); NodeGroup & new_node_group = createNodeGroup(group_name + "_nodes", replace_group); ElementGroups::iterator it = element_groups.find(group_name); if (it != element_groups.end()) { if (replace_group) { it->second->empty(); AKANTU_DEBUG_OUT(); return *(it->second); } else AKANTU_EXCEPTION("Trying to create a element group that already exists:" << group_name); } std::stringstream sstr; sstr << this->id << ":" << group_name << "_element_group"; ElementGroup * element_group = new ElementGroup( group_name, mesh, new_node_group, dimension, sstr.str(), memory_id); std::stringstream sstr_nodes; sstr_nodes << group_name << "_nodes"; node_groups[sstr_nodes.str()] = &new_node_group; element_groups[group_name] = element_group; AKANTU_DEBUG_OUT(); return *element_group; } /* -------------------------------------------------------------------------- */ void GroupManager::destroyElementGroup(const std::string & group_name, bool destroy_node_group) { AKANTU_DEBUG_IN(); ElementGroups::iterator eit = element_groups.find(group_name); ElementGroups::iterator eend = element_groups.end(); if (eit != eend) { if (destroy_node_group) destroyNodeGroup(eit->second->getNodeGroup().getName()); delete (eit->second); element_groups.erase(eit); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GroupManager::destroyAllElementGroups(bool destroy_node_groups) { AKANTU_DEBUG_IN(); ElementGroups::iterator eit = element_groups.begin(); ElementGroups::iterator eend = element_groups.end(); for (; eit != eend; ++eit) { if (destroy_node_groups) destroyNodeGroup(eit->second->getNodeGroup().getName()); delete (eit->second); } element_groups.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ElementGroup & GroupManager::createElementGroup(const std::string & group_name, UInt dimension, NodeGroup & node_group) { AKANTU_DEBUG_IN(); if (element_groups.find(group_name) != element_groups.end()) AKANTU_EXCEPTION( "Trying to create a element group that already exists:" << group_name); ElementGroup * element_group = new ElementGroup(group_name, mesh, node_group, dimension, id + ":" + group_name + "_element_group", memory_id); element_groups[group_name] = element_group; AKANTU_DEBUG_OUT(); return *element_group; } /* -------------------------------------------------------------------------- */ template <typename T> ElementGroup & GroupManager::createFilteredElementGroup( const std::string & group_name, UInt dimension, const NodeGroup & node_group, T & filter) { AKANTU_DEBUG_IN(); ElementGroup * element_group = NULL; if (T::type == FilterFunctor::_node_filter_functor) { NodeGroup & filtered_node_group = this->createFilteredNodeGroup( group_name + "_nodes", node_group, filter); element_group = &(this->createElementGroup(group_name, dimension, filtered_node_group)); } else if (T::type == FilterFunctor::_element_filter_functor) { AKANTU_DEBUG_ERROR( "Cannot handle an ElementFilter yet. Needs to be implemented."); } AKANTU_DEBUG_OUT(); return *element_group; } /* -------------------------------------------------------------------------- */ class ClusterSynchronizer : public DataAccessor<Element> { typedef std::set<std::pair<UInt, UInt> > DistantIDs; public: ClusterSynchronizer(GroupManager & group_manager, UInt element_dimension, std::string cluster_name_prefix, ElementTypeMapArray<UInt> & element_to_fragment, ElementSynchronizer & element_synchronizer, UInt nb_cluster) : group_manager(group_manager), element_dimension(element_dimension), cluster_name_prefix(cluster_name_prefix), element_to_fragment(element_to_fragment), element_synchronizer(element_synchronizer), nb_cluster(nb_cluster) {} UInt synchronize() { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); UInt rank = comm.whoAmI(); UInt nb_proc = comm.getNbProc(); /// find starting index to renumber local clusters Array<UInt> nb_cluster_per_proc(nb_proc); nb_cluster_per_proc(rank) = nb_cluster; comm.allGather(nb_cluster_per_proc); starting_index = std::accumulate(nb_cluster_per_proc.begin(), nb_cluster_per_proc.begin() + rank, 0); UInt global_nb_fragment = std::accumulate(nb_cluster_per_proc.begin() + rank, nb_cluster_per_proc.end(), starting_index); /// create the local to distant cluster pairs with neighbors element_synchronizer.computeBufferSize(*this, _gst_gm_clusters); element_synchronizer.asynchronousSynchronize(*this, _gst_gm_clusters); element_synchronizer.waitEndSynchronize(*this, _gst_gm_clusters); /// count total number of pairs Array<int> nb_pairs(nb_proc); // This is potentially a bug for more than // 2**31 pairs, but due to a all gatherv after // it must be int to match MPI interfaces nb_pairs(rank) = distant_ids.size(); comm.allGather(nb_pairs); UInt total_nb_pairs = std::accumulate(nb_pairs.begin(), nb_pairs.end(), 0); /// generate pairs global array UInt local_pair_index = std::accumulate(nb_pairs.storage(), nb_pairs.storage() + rank, 0); Array<UInt> total_pairs(total_nb_pairs, 2); DistantIDs::iterator ids_it = distant_ids.begin(); DistantIDs::iterator ids_end = distant_ids.end(); for (; ids_it != ids_end; ++ids_it, ++local_pair_index) { total_pairs(local_pair_index, 0) = ids_it->first; total_pairs(local_pair_index, 1) = ids_it->second; } /// communicate pairs to all processors nb_pairs *= 2; comm.allGatherV(total_pairs, nb_pairs); /// renumber clusters /// generate fragment list std::vector<std::set<UInt> > global_clusters; UInt total_nb_cluster = 0; Array<bool> is_fragment_in_cluster(global_nb_fragment, 1, false); std::queue<UInt> fragment_check_list; while (total_pairs.getSize() != 0) { /// create a new cluster ++total_nb_cluster; global_clusters.resize(total_nb_cluster); std::set<UInt> & current_cluster = global_clusters[total_nb_cluster - 1]; UInt first_fragment = total_pairs(0, 0); UInt second_fragment = total_pairs(0, 1); total_pairs.erase(0); fragment_check_list.push(first_fragment); fragment_check_list.push(second_fragment); while (!fragment_check_list.empty()) { UInt current_fragment = fragment_check_list.front(); UInt * total_pairs_end = total_pairs.storage() + total_pairs.getSize() * 2; UInt * fragment_found = std::find(total_pairs.storage(), total_pairs_end, current_fragment); if (fragment_found != total_pairs_end) { UInt position = fragment_found - total_pairs.storage(); UInt pair = position / 2; UInt other_index = (position + 1) % 2; fragment_check_list.push(total_pairs(pair, other_index)); total_pairs.erase(pair); } else { fragment_check_list.pop(); current_cluster.insert(current_fragment); is_fragment_in_cluster(current_fragment) = true; } } } /// add to FragmentToCluster all local fragments for (UInt c = 0; c < global_nb_fragment; ++c) { if (!is_fragment_in_cluster(c)) { ++total_nb_cluster; global_clusters.resize(total_nb_cluster); std::set<UInt> & current_cluster = global_clusters[total_nb_cluster - 1]; current_cluster.insert(c); } } /// reorganize element groups to match global clusters for (UInt c = 0; c < global_clusters.size(); ++c) { /// create new element group corresponding to current cluster std::stringstream sstr; sstr << cluster_name_prefix << "_" << c; ElementGroup & cluster = group_manager.createElementGroup(sstr.str(), element_dimension, true); std::set<UInt>::iterator it = global_clusters[c].begin(); std::set<UInt>::iterator end = global_clusters[c].end(); /// append to current element group all fragments that belong to /// the same cluster if they exist for (; it != end; ++it) { Int local_index = *it - starting_index; if (local_index < 0 || local_index >= Int(nb_cluster)) continue; std::stringstream tmp_sstr; tmp_sstr << "tmp_" << cluster_name_prefix << "_" << local_index; GroupManager::element_group_iterator eg_it = group_manager.element_group_find(tmp_sstr.str()); AKANTU_DEBUG_ASSERT(eg_it != group_manager.element_group_end(), "Temporary fragment \"" << tmp_sstr.str() << "\" not found"); cluster.append(*(eg_it->second)); group_manager.destroyElementGroup(tmp_sstr.str(), true); } } return total_nb_cluster; } private: /// functions for parallel communications inline UInt getNbData(const Array<Element> & elements, const SynchronizationTag & tag) const { if (tag == _gst_gm_clusters) return elements.getSize() * sizeof(UInt); return 0; } inline void packData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) const { if (tag != _gst_gm_clusters) return; Array<Element>::const_iterator<> el_it = elements.begin(); Array<Element>::const_iterator<> el_end = elements.end(); for (; el_it != el_end; ++el_it) { const Element & el = *el_it; /// for each element pack its global cluster index buffer << element_to_fragment(el.type, el.ghost_type)(el.element) + starting_index; } } inline void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) { if (tag != _gst_gm_clusters) return; Array<Element>::const_iterator<> el_it = elements.begin(); Array<Element>::const_iterator<> el_end = elements.end(); for (; el_it != el_end; ++el_it) { UInt distant_cluster; buffer >> distant_cluster; const Element & el = *el_it; UInt local_cluster = element_to_fragment(el.type, el.ghost_type)(el.element) + starting_index; distant_ids.insert(std::make_pair(local_cluster, distant_cluster)); } } private: GroupManager & group_manager; UInt element_dimension; std::string cluster_name_prefix; ElementTypeMapArray<UInt> & element_to_fragment; ElementSynchronizer & element_synchronizer; UInt nb_cluster; DistantIDs distant_ids; UInt starting_index; }; /* -------------------------------------------------------------------------- */ /// \todo this function doesn't work in 1D UInt GroupManager::createBoundaryGroupFromGeometry() { UInt spatial_dimension = mesh.getSpatialDimension(); return createClusters(spatial_dimension - 1, "boundary"); } /* -------------------------------------------------------------------------- */ //// \todo if needed element list construction can be optimized by //// templating the filter class UInt GroupManager::createClusters( UInt element_dimension, std::string cluster_name_prefix, const GroupManager::ClusteringFilter & filter, ElementSynchronizer * element_synchronizer, Mesh * mesh_facets) { AKANTU_DEBUG_IN(); UInt nb_proc = StaticCommunicator::getStaticCommunicator().getNbProc(); std::string tmp_cluster_name_prefix = cluster_name_prefix; ElementTypeMapArray<UInt> * element_to_fragment = NULL; if (nb_proc > 1 && element_synchronizer) { element_to_fragment = new ElementTypeMapArray<UInt>("element_to_fragment", id, memory_id); mesh.initElementTypeMapArray(*element_to_fragment, 1, element_dimension, false, _ek_not_defined, true); tmp_cluster_name_prefix = "tmp_" + tmp_cluster_name_prefix; } /// Get facets bool mesh_facets_created = false; if (!mesh_facets && element_dimension > 0) { mesh_facets = new Mesh(mesh.getSpatialDimension(), mesh.getNodes().getID(), "mesh_facets_for_clusters"); mesh_facets->defineMeshParent(mesh); MeshUtils::buildAllFacets(mesh, *mesh_facets, element_dimension, element_dimension - 1); } ElementTypeMapArray<bool> seen_elements("seen_elements", id, memory_id); mesh.initElementTypeMapArray(seen_elements, 1, element_dimension, false, _ek_not_defined, true); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Element el; el.ghost_type = ghost_type; Mesh::type_iterator type_it = mesh.firstType(element_dimension, ghost_type, _ek_not_defined); Mesh::type_iterator type_end = mesh.lastType(element_dimension, ghost_type, _ek_not_defined); for (; type_it != type_end; ++type_it) { el.type = *type_it; el.kind = Mesh::getKind(*type_it); UInt nb_element = mesh.getNbElement(*type_it, ghost_type); Array<bool> & seen_elements_array = seen_elements(el.type, ghost_type); for (UInt e = 0; e < nb_element; ++e) { el.element = e; if (!filter(el)) seen_elements_array(e) = true; } } } Array<bool> checked_node(mesh.getNbNodes(), 1, false); UInt nb_cluster = 0; /// keep looping until all elements are seen for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Element uns_el; uns_el.ghost_type = ghost_type; Mesh::type_iterator type_it = mesh.firstType(element_dimension, ghost_type, _ek_not_defined); Mesh::type_iterator type_end = mesh.lastType(element_dimension, ghost_type, _ek_not_defined); for (; type_it != type_end; ++type_it) { uns_el.type = *type_it; Array<bool> & seen_elements_vec = seen_elements(uns_el.type, uns_el.ghost_type); for (UInt e = 0; e < seen_elements_vec.getSize(); ++e) { // skip elements that have been already seen if (seen_elements_vec(e) == true) continue; // set current element uns_el.element = e; seen_elements_vec(e) = true; /// create a new cluster std::stringstream sstr; sstr << tmp_cluster_name_prefix << "_" << nb_cluster; ElementGroup & cluster = createElementGroup(sstr.str(), element_dimension, true); ++nb_cluster; // point element are cluster by themself if (element_dimension == 0) { cluster.add(uns_el); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(uns_el.type); Vector<UInt> connect = mesh.getConnectivity(uns_el.type, uns_el.ghost_type) .begin(nb_nodes_per_element)[uns_el.element]; for (UInt n = 0; n < nb_nodes_per_element; ++n) { /// add element's nodes to the cluster UInt node = connect[n]; if (!checked_node(node)) { cluster.addNode(node); checked_node(node) = true; } } continue; } std::queue<Element> element_to_add; element_to_add.push(uns_el); /// keep looping until current cluster is complete (no more /// connected elements) while (!element_to_add.empty()) { /// take first element and erase it in the queue Element el = element_to_add.front(); element_to_add.pop(); /// if parallel, store cluster index per element if (nb_proc > 1 && element_synchronizer) (*element_to_fragment)(el.type, el.ghost_type)(el.element) = nb_cluster - 1; /// add current element to the cluster cluster.add(el); const Array<Element> & element_to_facet = mesh_facets->getSubelementToElement(el.type, el.ghost_type); UInt nb_facet_per_element = element_to_facet.getNbComponent(); for (UInt f = 0; f < nb_facet_per_element; ++f) { const Element & facet = element_to_facet(el.element, f); if (facet == ElementNull) continue; const std::vector<Element> & connected_elements = mesh_facets->getElementToSubelement( facet.type, facet.ghost_type)(facet.element); for (UInt elem = 0; elem < connected_elements.size(); ++elem) { const Element & check_el = connected_elements[elem]; // check if this element has to be skipped if (check_el == ElementNull || check_el == el) continue; Array<bool> & seen_elements_vec_current = seen_elements(check_el.type, check_el.ghost_type); if (seen_elements_vec_current(check_el.element) == false) { seen_elements_vec_current(check_el.element) = true; element_to_add.push(check_el); } } } UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(el.type); Vector<UInt> connect = mesh.getConnectivity(el.type, el.ghost_type) .begin(nb_nodes_per_element)[el.element]; for (UInt n = 0; n < nb_nodes_per_element; ++n) { /// add element's nodes to the cluster UInt node = connect[n]; if (!checked_node(node)) { cluster.addNode(node, false); checked_node(node) = true; } } } } } } if (nb_proc > 1 && element_synchronizer) { ClusterSynchronizer cluster_synchronizer( *this, element_dimension, cluster_name_prefix, *element_to_fragment, *element_synchronizer, nb_cluster); nb_cluster = cluster_synchronizer.synchronize(); delete element_to_fragment; } if (mesh_facets_created) delete mesh_facets; if (mesh.isDistributed()) this->synchronizeGroupNames(); AKANTU_DEBUG_OUT(); return nb_cluster; } /* -------------------------------------------------------------------------- */ template <typename T> void GroupManager::createGroupsFromMeshData(const std::string & dataset_name) { std::set<std::string> group_names; const ElementTypeMapArray<T> & datas = mesh.getData<T>(dataset_name); typedef typename ElementTypeMapArray<T>::type_iterator type_iterator; std::map<std::string, UInt> group_dim; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { type_iterator type_it = datas.firstType(_all_dimensions, *gt); type_iterator type_end = datas.lastType(_all_dimensions, *gt); for (; type_it != type_end; ++type_it) { const Array<T> & dataset = datas(*type_it, *gt); UInt nb_element = mesh.getNbElement(*type_it, *gt); AKANTU_DEBUG_ASSERT(dataset.getSize() == nb_element, "Not the same number of elements (" << *type_it << ":" << *gt << ") in the map from MeshData (" << dataset.getSize() << ") " << dataset_name << " and in the mesh (" << nb_element << ")!"); for (UInt e(0); e < nb_element; ++e) { std::stringstream sstr; sstr << dataset(e); std::string gname = sstr.str(); group_names.insert(gname); std::map<std::string, UInt>::iterator it = group_dim.find(gname); if (it == group_dim.end()) { group_dim[gname] = mesh.getSpatialDimension(*type_it); } else { it->second = std::max(it->second, mesh.getSpatialDimension(*type_it)); } } } } std::set<std::string>::iterator git = group_names.begin(); std::set<std::string>::iterator gend = group_names.end(); for (; git != gend; ++git) createElementGroup(*git, group_dim[*git]); if (mesh.isDistributed()) this->synchronizeGroupNames(); Element el; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { el.ghost_type = *gt; type_iterator type_it = datas.firstType(_all_dimensions, *gt); type_iterator type_end = datas.lastType(_all_dimensions, *gt); for (; type_it != type_end; ++type_it) { el.type = *type_it; const Array<T> & dataset = datas(*type_it, *gt); UInt nb_element = mesh.getNbElement(*type_it, *gt); AKANTU_DEBUG_ASSERT(dataset.getSize() == nb_element, "Not the same number of elements in the map from " "MeshData and in the mesh!"); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(el.type); Array<UInt>::const_iterator<Vector<UInt> > cit = mesh.getConnectivity(*type_it, *gt).begin(nb_nodes_per_element); for (UInt e(0); e < nb_element; ++e, ++cit) { el.element = e; std::stringstream sstr; sstr << dataset(e); ElementGroup & group = getElementGroup(sstr.str()); group.add(el, false, false); const Vector<UInt> & connect = *cit; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connect[n]; group.addNode(node, false); } } } } git = group_names.begin(); for (; git != gend; ++git) { getElementGroup(*git).optimize(); } } template void GroupManager::createGroupsFromMeshData<std::string>( const std::string & dataset_name); template void GroupManager::createGroupsFromMeshData<UInt>(const std::string & dataset_name); /* -------------------------------------------------------------------------- */ void GroupManager::createElementGroupFromNodeGroup( const std::string & name, const std::string & node_group_name, UInt dimension) { NodeGroup & node_group = getNodeGroup(node_group_name); ElementGroup & group = createElementGroup(name, dimension, node_group); group.fillFromNodeGroup(); } /* -------------------------------------------------------------------------- */ void GroupManager::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "GroupManager [" << std::endl; std::set<std::string> node_group_seen; for (const_element_group_iterator it(element_group_begin()); it != element_group_end(); ++it) { it->second->printself(stream, indent + 1); node_group_seen.insert(it->second->getNodeGroup().getName()); } for (const_node_group_iterator it(node_group_begin()); it != node_group_end(); ++it) { if (node_group_seen.find(it->second->getName()) == node_group_seen.end()) it->second->printself(stream, indent + 1); } stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ UInt GroupManager::getNbElementGroups(UInt dimension) const { if (dimension == _all_dimensions) return element_groups.size(); ElementGroups::const_iterator it = element_groups.begin(); ElementGroups::const_iterator end = element_groups.end(); UInt count = 0; for (; it != end; ++it) count += (it->second->getDimension() == dimension); return count; } /* -------------------------------------------------------------------------- */ void GroupManager::checkAndAddGroups(CommunicationBuffer & buffer) { AKANTU_DEBUG_IN(); UInt nb_node_group; buffer >> nb_node_group; AKANTU_DEBUG_INFO("Received " << nb_node_group << " node group names"); for (UInt ng = 0; ng < nb_node_group; ++ng) { std::string node_group_name; buffer >> node_group_name; if (node_groups.find(node_group_name) == node_groups.end()) { this->createNodeGroup(node_group_name); } AKANTU_DEBUG_INFO("Received node goup name: " << node_group_name); } UInt nb_element_group; buffer >> nb_element_group; AKANTU_DEBUG_INFO("Received " << nb_element_group << " element group names"); for (UInt eg = 0; eg < nb_element_group; ++eg) { std::string element_group_name; buffer >> element_group_name; std::string node_group_name; buffer >> node_group_name; UInt dim; buffer >> dim; AKANTU_DEBUG_INFO("Received element group name: " << element_group_name << " corresponding to a " << Int(dim) << "D group with node group " << node_group_name); NodeGroup & node_group = *node_groups[node_group_name]; if (element_groups.find(element_group_name) == element_groups.end()) { this->createElementGroup(element_group_name, dim, node_group); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GroupManager::fillBufferWithGroupNames( DynamicCommunicationBuffer & comm_buffer) const { AKANTU_DEBUG_IN(); // packing node group names; UInt nb_groups = this->node_groups.size(); comm_buffer << nb_groups; AKANTU_DEBUG_INFO("Sending " << nb_groups << " node group names"); NodeGroups::const_iterator nnames_it = node_groups.begin(); NodeGroups::const_iterator nnames_end = node_groups.end(); for (; nnames_it != nnames_end; ++nnames_it) { std::string node_group_name = nnames_it->first; comm_buffer << node_group_name; AKANTU_DEBUG_INFO("Sending node goupe name: " << node_group_name); } // packing element group names with there associated node group name nb_groups = this->element_groups.size(); comm_buffer << nb_groups; AKANTU_DEBUG_INFO("Sending " << nb_groups << " element group names"); ElementGroups::const_iterator gnames_it = this->element_groups.begin(); ElementGroups::const_iterator gnames_end = this->element_groups.end(); for (; gnames_it != gnames_end; ++gnames_it) { ElementGroup & element_group = *(gnames_it->second); std::string element_group_name = gnames_it->first; std::string node_group_name = element_group.getNodeGroup().getName(); UInt dim = element_group.getDimension(); comm_buffer << element_group_name; comm_buffer << node_group_name; comm_buffer << dim; AKANTU_DEBUG_INFO("Sending element group name: " << element_group_name << " corresponding to a " << Int(dim) << "D group with the node group " << node_group_name); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GroupManager::synchronizeGroupNames() { AKANTU_DEBUG_IN(); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int nb_proc = comm.getNbProc(); Int my_rank = comm.whoAmI(); if (nb_proc == 1) return; if (my_rank == 0) { for (Int p = 1; p < nb_proc; ++p) { CommunicationStatus status; comm.probe<char>(p, p, status); AKANTU_DEBUG_INFO("Got " << printMemorySize<char>(status.getSize()) << " from proc " << p); CommunicationBuffer recv_buffer(status.getSize()); comm.receive(recv_buffer, p, p); this->checkAndAddGroups(recv_buffer); } DynamicCommunicationBuffer comm_buffer; this->fillBufferWithGroupNames(comm_buffer); UInt buffer_size = comm_buffer.getSize(); comm.broadcast(buffer_size, 0); AKANTU_DEBUG_INFO("Initiating broadcast with " << printMemorySize<char>(comm_buffer.getSize())); comm.broadcast(comm_buffer, 0); } else { DynamicCommunicationBuffer comm_buffer; this->fillBufferWithGroupNames(comm_buffer); AKANTU_DEBUG_INFO("Sending " << printMemorySize<char>(comm_buffer.getSize()) << " to proc " << 0); comm.send(comm_buffer, 0, my_rank); UInt buffer_size = 0; comm.broadcast(buffer_size, 0); AKANTU_DEBUG_INFO("Receiving broadcast with " << printMemorySize<char>(comm_buffer.getSize())); CommunicationBuffer recv_buffer(buffer_size); comm.broadcast(recv_buffer, 0); this->checkAndAddGroups(recv_buffer); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ const ElementGroup & GroupManager::getElementGroup(const std::string & name) const { const_element_group_iterator it = element_group_find(name); if (it == element_group_end()) { AKANTU_EXCEPTION("There are no element groups named " << name << " associated to the group manager: " << id); } return *(it->second); } /* -------------------------------------------------------------------------- */ ElementGroup & GroupManager::getElementGroup(const std::string & name) { element_group_iterator it = element_group_find(name); if (it == element_group_end()) { AKANTU_EXCEPTION("There are no element groups named " << name << " associated to the group manager: " << id); } return *(it->second); } /* -------------------------------------------------------------------------- */ const NodeGroup & GroupManager::getNodeGroup(const std::string & name) const { const_node_group_iterator it = node_group_find(name); if (it == node_group_end()) { AKANTU_EXCEPTION("There are no node groups named " << name << " associated to the group manager: " << id); } return *(it->second); } /* -------------------------------------------------------------------------- */ NodeGroup & GroupManager::getNodeGroup(const std::string & name) { node_group_iterator it = node_group_find(name); if (it == node_group_end()) { AKANTU_EXCEPTION("There are no node groups named " << name << " associated to the group manager: " << id); } return *(it->second); } -__END_AKANTU__ +} // akantu diff --git a/src/mesh/group_manager.hh b/src/mesh/group_manager.hh index 8537c8b00..1147edbfa 100644 --- a/src/mesh/group_manager.hh +++ b/src/mesh/group_manager.hh @@ -1,296 +1,296 @@ /** * @file group_manager.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Dana Christen <dana.christen@gmail.com> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Mon Nov 16 2015 * * @brief Stores information relevent to the notion of element and nodes *groups. * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_GROUP_MANAGER_HH__ #define __AKANTU_GROUP_MANAGER_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "element_type_map.hh" /* -------------------------------------------------------------------------- */ #include <set> /* -------------------------------------------------------------------------- */ namespace akantu { class ElementGroup; class NodeGroup; class Mesh; class Element; class ElementSynchronizer; template <bool> class CommunicationBufferTemplated; namespace dumper { class Field; } } -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ class GroupManager { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ private: typedef std::map<std::string, ElementGroup *> ElementGroups; typedef std::map<std::string, NodeGroup *> NodeGroups; public: typedef std::set<ElementType> GroupManagerTypeSet; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: GroupManager(const Mesh & mesh, const ID & id = "group_manager", const MemoryID & memory_id = 0); virtual ~GroupManager(); /* ------------------------------------------------------------------------ */ /* Groups iterators */ /* ------------------------------------------------------------------------ */ public: typedef NodeGroups::iterator node_group_iterator; typedef ElementGroups::iterator element_group_iterator; typedef NodeGroups::const_iterator const_node_group_iterator; typedef ElementGroups::const_iterator const_element_group_iterator; #ifndef SWIG #define AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(group_type, function, \ param_in, param_out) \ inline BOOST_PP_CAT(BOOST_PP_CAT(const_, group_type), _iterator) \ BOOST_PP_CAT(BOOST_PP_CAT(group_type, _), function)(param_in) const { \ return BOOST_PP_CAT(group_type, s).function(param_out); \ }; \ \ inline BOOST_PP_CAT(group_type, _iterator) \ BOOST_PP_CAT(BOOST_PP_CAT(group_type, _), function)(param_in) { \ return BOOST_PP_CAT(group_type, s).function(param_out); \ } #define AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(group_type, function) \ AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION( \ group_type, function, BOOST_PP_EMPTY(), BOOST_PP_EMPTY()) AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(node_group, begin); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(node_group, end); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(element_group, begin); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(element_group, end); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(element_group, find, const std::string & name, name); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(node_group, find, const std::string & name, name); #endif /* ------------------------------------------------------------------------ */ /* Clustering filter */ /* ------------------------------------------------------------------------ */ public: class ClusteringFilter { public: virtual bool operator()(const Element &) const { return true; } }; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// create an empty node group NodeGroup & createNodeGroup(const std::string & group_name, bool replace_group = false); /// create a node group from another node group but filtered template <typename T> NodeGroup & createFilteredNodeGroup(const std::string & group_name, const NodeGroup & node_group, T & filter); /// destroy a node group void destroyNodeGroup(const std::string & group_name); /// create an element group and the associated node group ElementGroup & createElementGroup(const std::string & group_name, UInt dimension = _all_dimensions, bool replace_group = false); /// create an element group from another element group but filtered template <typename T> ElementGroup & createFilteredElementGroup(const std::string & group_name, UInt dimension, const NodeGroup & node_group, T & filter); /// destroy an element group and the associated node group void destroyElementGroup(const std::string & group_name, bool destroy_node_group = false); /// destroy all element groups and the associated node groups void destroyAllElementGroups(bool destroy_node_groups = false); /// create a element group using an existing node group ElementGroup & createElementGroup(const std::string & group_name, UInt dimension, NodeGroup & node_group); /// create groups based on values stored in a given mesh data template <typename T> void createGroupsFromMeshData(const std::string & dataset_name); /// create boundaries group by a clustering algorithm \todo extend to parallel UInt createBoundaryGroupFromGeometry(); /// create element clusters for a given dimension UInt createClusters(UInt element_dimension, std::string cluster_name_prefix = "cluster", const ClusteringFilter & filter = ClusteringFilter(), ElementSynchronizer * element_synchronizer = NULL, Mesh * mesh_facets = NULL); /// Create an ElementGroup based on a NodeGroup void createElementGroupFromNodeGroup(const std::string & name, const std::string & node_group, UInt dimension = _all_dimensions); virtual void printself(std::ostream & stream, int indent = 0) const; /// this function insure that the group names are present on all processors /// /!\ it is a SMP call void synchronizeGroupNames(); /// register an elemental field to the given group name (overloading for /// ElementalPartionField) #ifndef SWIG template <typename T, template <bool> class dump_type> inline dumper::Field * createElementalField( const ElementTypeMapArray<T> & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap<UInt> nb_data_per_elem = ElementTypeMap<UInt>()); /// register an elemental field to the given group name (overloading for /// ElementalField) template <typename T, template <class> class ret_type, template <class, template <class> class, bool> class dump_type> inline dumper::Field * createElementalField( const ElementTypeMapArray<T> & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap<UInt> nb_data_per_elem = ElementTypeMap<UInt>()); /// register an elemental field to the given group name (overloading for /// MaterialInternalField) template <typename T, /// type of InternalMaterialField template <typename, bool filtered> class dump_type> inline dumper::Field * createElementalField(const ElementTypeMapArray<T> & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap<UInt> nb_data_per_elem); template <typename type, bool flag, template <class, bool> class ftype> inline dumper::Field * createNodalField(const ftype<type, flag> * field, const std::string & group_name, UInt padding_size = 0); template <typename type, bool flag, template <class, bool> class ftype> inline dumper::Field * createStridedNodalField(const ftype<type, flag> * field, const std::string & group_name, UInt size, UInt stride, UInt padding_size); protected: /// fill a buffer with all the group names void fillBufferWithGroupNames( CommunicationBufferTemplated<false> & comm_buffer) const; /// take a buffer and create the missing groups localy void checkAndAddGroups(CommunicationBufferTemplated<true> & buffer); /// register an elemental field to the given group name template <class dump_type, typename field_type> inline dumper::Field * createElementalField(const field_type & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap<UInt> nb_data_per_elem); /// register an elemental field to the given group name template <class dump_type, typename field_type> inline dumper::Field * createElementalFilteredField(const field_type & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap<UInt> nb_data_per_elem); #endif /* ------------------------------------------------------------------------ */ /* Accessor */ /* ------------------------------------------------------------------------ */ public: const ElementGroup & getElementGroup(const std::string & name) const; const NodeGroup & getNodeGroup(const std::string & name) const; ElementGroup & getElementGroup(const std::string & name); NodeGroup & getNodeGroup(const std::string & name); UInt getNbElementGroups(UInt dimension = _all_dimensions) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id to create element and node groups ID id; /// memory_id to create element and node groups MemoryID memory_id; /// list of the node groups managed NodeGroups node_groups; /// list of the element groups managed ElementGroups element_groups; /// Mesh to which the element belongs const Mesh & mesh; }; /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const GroupManager & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_GROUP_MANAGER_HH__ */ diff --git a/src/mesh/group_manager_inline_impl.cc b/src/mesh/group_manager_inline_impl.cc index c6d3b6dce..d6ebfbbf2 100644 --- a/src/mesh/group_manager_inline_impl.cc +++ b/src/mesh/group_manager_inline_impl.cc @@ -1,207 +1,207 @@ /** * @file group_manager_inline_impl.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Dana Christen <dana.christen@gmail.com> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Tue Dec 08 2015 * * @brief Stores information relevent to the notion of domain boundary and * surfaces. * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "dumper_field.hh" #include "element_group.hh" #include "element_type_map_filter.hh" #ifdef AKANTU_USE_IOHELPER #include "dumper_nodal_field.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <typename T, template <bool> class dump_type> dumper::Field * GroupManager::createElementalField( const ElementTypeMapArray<T> & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap<UInt> nb_data_per_elem) { const ElementTypeMapArray<T> * field_ptr = &field; if (field_ptr == NULL) return NULL; if (group_name == "all") return this->createElementalField<dump_type<false> >( field, group_name, spatial_dimension, kind, nb_data_per_elem); else return this->createElementalFilteredField<dump_type<true> >( field, group_name, spatial_dimension, kind, nb_data_per_elem); } /* -------------------------------------------------------------------------- */ template <typename T, template <class> class T2, template <class, template <class> class, bool> class dump_type> dumper::Field * GroupManager::createElementalField( const ElementTypeMapArray<T> & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap<UInt> nb_data_per_elem) { const ElementTypeMapArray<T> * field_ptr = &field; if (field_ptr == NULL) return NULL; if (group_name == "all") return this->createElementalField<dump_type<T, T2, false> >( field, group_name, spatial_dimension, kind, nb_data_per_elem); else return this->createElementalFilteredField<dump_type<T, T2, true> >( field, group_name, spatial_dimension, kind, nb_data_per_elem); } /* -------------------------------------------------------------------------- */ template <typename T, template <typename T2, bool filtered> class dump_type> ///< type of InternalMaterialField dumper::Field * GroupManager::createElementalField(const ElementTypeMapArray<T> & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap<UInt> nb_data_per_elem) { const ElementTypeMapArray<T> * field_ptr = &field; if (field_ptr == NULL) return NULL; if (group_name == "all") return this->createElementalField<dump_type<T, false> >( field, group_name, spatial_dimension, kind, nb_data_per_elem); else return this->createElementalFilteredField<dump_type<T, true> >( field, group_name, spatial_dimension, kind, nb_data_per_elem); } /* -------------------------------------------------------------------------- */ template <typename dump_type, typename field_type> dumper::Field * GroupManager::createElementalField( const field_type & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap<UInt> nb_data_per_elem) { const field_type * field_ptr = &field; if (field_ptr == NULL) return NULL; if (group_name != "all") throw; dumper::Field * dumper = new dump_type(field, spatial_dimension, _not_ghost, kind); dumper->setNbDataPerElem(nb_data_per_elem); return dumper; } /* -------------------------------------------------------------------------- */ template <typename dump_type, typename field_type> dumper::Field * GroupManager::createElementalFilteredField( const field_type & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap<UInt> nb_data_per_elem) { const field_type * field_ptr = &field; if (field_ptr == NULL) return NULL; if (group_name == "all") throw; typedef typename field_type::type T; ElementGroup & group = this->getElementGroup(group_name); UInt dim = group.getDimension(); if (dim != spatial_dimension) throw; const ElementTypeMapArray<UInt> & elemental_filter = group.getElements(); ElementTypeMapArrayFilter<T> * filtered = new ElementTypeMapArrayFilter<T>( field, elemental_filter, nb_data_per_elem); dumper::Field * dumper = new dump_type(*filtered, dim, _not_ghost, kind); dumper->setNbDataPerElem(nb_data_per_elem); return dumper; } /* -------------------------------------------------------------------------- */ template <typename type, bool flag, template <class, bool> class ftype> dumper::Field * GroupManager::createNodalField(const ftype<type, flag> * field, const std::string & group_name, UInt padding_size) { if (field == NULL) return NULL; if (group_name == "all") { typedef typename dumper::NodalField<type, false> DumpType; DumpType * dumper = new DumpType(*field, 0, 0, NULL); dumper->setPadding(padding_size); return dumper; } else { ElementGroup & group = this->getElementGroup(group_name); const Array<UInt> * nodal_filter = &(group.getNodes()); typedef typename dumper::NodalField<type, true> DumpType; DumpType * dumper = new DumpType(*field, 0, 0, nodal_filter); dumper->setPadding(padding_size); return dumper; } return NULL; } /* -------------------------------------------------------------------------- */ template <typename type, bool flag, template <class, bool> class ftype> dumper::Field * GroupManager::createStridedNodalField(const ftype<type, flag> * field, const std::string & group_name, UInt size, UInt stride, UInt padding_size) { if (field == NULL) return NULL; if (group_name == "all") { typedef typename dumper::NodalField<type, false> DumpType; DumpType * dumper = new DumpType(*field, size, stride, NULL); dumper->setPadding(padding_size); return dumper; } else { ElementGroup & group = this->getElementGroup(group_name); const Array<UInt> * nodal_filter = &(group.getNodes()); typedef typename dumper::NodalField<type, true> DumpType; DumpType * dumper = new DumpType(*field, size, stride, nodal_filter); dumper->setPadding(padding_size); return dumper; } return NULL; } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #endif diff --git a/src/mesh/mesh_accessor.hh b/src/mesh/mesh_accessor.hh index 5c4bdef09..abf01fe45 100644 --- a/src/mesh/mesh_accessor.hh +++ b/src/mesh/mesh_accessor.hh @@ -1,129 +1,129 @@ /** * @file mesh_accessor.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Jun 30 2015 * * @brief this class allow to access some private member of mesh it is used for * IO for examples * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "mesh.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_ACCESSOR_HH__ #define __AKANTU_MESH_ACCESSOR_HH__ namespace akantu { class NodeSynchronizer; class ElementSynchronizer; } // akantu -__BEGIN_AKANTU__ +namespace akantu { class MeshAccessor { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshAccessor(Mesh & mesh) : _mesh(mesh){}; virtual ~MeshAccessor(){}; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the global number of nodes inline UInt getNbGlobalNodes() const { return this->_mesh.nb_global_nodes; }; /// set the global number of nodes inline void setNbGlobalNodes(UInt nb_global_nodes) { this->_mesh.nb_global_nodes = nb_global_nodes; }; /// set the mesh as being distributed inline void setDistributed() { this->_mesh.is_distributed = true; } /// get a pointer to the nodes_global_ids Array<UInt> and create it if /// necessary inline Array<UInt> & getNodesGlobalIds() { return *(this->_mesh.getNodesGlobalIdsPointer()); } /// get a pointer to the nodes_type Array<Int> and create it if necessary inline Array<NodeType> & getNodesType() { return *(this->_mesh.getNodesTypePointer()); } /// get a pointer to the coordinates Array inline Array<Real> & getNodes() { return *(this->_mesh.getNodesPointer()); } /// get a pointer to the connectivity Array for the given type and create it /// if necessary inline Array<UInt> & getConnectivity(const ElementType & type, const GhostType & ghost_type = _not_ghost) { return *(this->_mesh.getConnectivityPointer(type, ghost_type)); } /// get a pointer to the element_to_subelement Array for the given type and /// create it if necessary inline Array<std::vector<Element> > & getElementToSubelement(const ElementType & type, const GhostType & ghost_type = _not_ghost) { return *(this->_mesh.getElementToSubelementPointer(type, ghost_type)); } /// get a pointer to the subelement_to_element Array for the given type and /// create it if necessary inline Array<Element> & getSubelementToElement(const ElementType & type, const GhostType & ghost_type = _not_ghost) { return *(this->_mesh.getSubelementToElementPointer(type, ghost_type)); } template <typename T> inline Array<T> & getData(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type = _not_ghost, UInt nb_component = 1, bool size_to_nb_element = true, bool resize_with_parent = false) { return *(this->_mesh.getDataPointer<T>(data_name, el_type, ghost_type, nb_component, size_to_nb_element, resize_with_parent)); } MeshData & getMeshData() { return this->_mesh.getMeshData(); } /// get the node synchonizer NodeSynchronizer & getNodeSynchronizer(); /// get the element synchonizer ElementSynchronizer & getElementSynchronizer(); private: Mesh & _mesh; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MESH_ACCESSOR_HH__ */ diff --git a/src/mesh/mesh_data.cc b/src/mesh/mesh_data.cc index 6c49bc088..f669598df 100644 --- a/src/mesh/mesh_data.cc +++ b/src/mesh/mesh_data.cc @@ -1,49 +1,49 @@ /** * @file mesh_data.cc * * @author Dana Christen <dana.christen@gmail.com> * * @date creation: Fri Apr 13 2012 * @date last modification: Sun Oct 19 2014 * * @brief Stores generic data loaded from the mesh file * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #include "mesh.hh" #include "mesh_data.hh" -__BEGIN_AKANTU__ +namespace akantu { MeshData::MeshData(const ID & _id, const ID & parent_id, const MemoryID & mem_id) : Memory(parent_id + ":" + _id, mem_id) { } MeshData::~MeshData() { ElementalDataMap::iterator it, end; for(it = elemental_data.begin(); it != elemental_data.end(); ++it) { delete it->second; } } -__END_AKANTU__ +} // akantu diff --git a/src/mesh/mesh_data.hh b/src/mesh/mesh_data.hh index 2a240f464..c2b943cc8 100644 --- a/src/mesh/mesh_data.hh +++ b/src/mesh/mesh_data.hh @@ -1,145 +1,145 @@ /** * @file mesh_data.hh * * @author Dana Christen <dana.christen@gmail.com> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri May 03 2013 * @date last modification: Thu Nov 05 2015 * * @brief Stores generic data loaded from the mesh file * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_DATA_HH__ #define __AKANTU_MESH_DATA_HH__ /* -------------------------------------------------------------------------- */ #include "element_type_map.hh" #include "aka_memory.hh" #include <map> #include <string> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { #define AKANTU_MESH_DATA_TYPES \ ((_tc_int, Int)) \ ((_tc_uint, UInt)) \ ((_tc_real, Real)) \ ((_tc_element, Element)) \ ((_tc_std_string, std::string)) \ ((_tc_std_vector_element, std::vector<Element>)) \ #define AKANTU_MESH_DATA_TUPLE_FIRST_ELEM(s, data, elem) BOOST_PP_TUPLE_ELEM(2, 0, elem) enum MeshDataTypeCode : int { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(AKANTU_MESH_DATA_TUPLE_FIRST_ELEM, , AKANTU_MESH_DATA_TYPES)), _tc_unknown }; class MeshData : public Memory { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ private: typedef MeshDataTypeCode TypeCode; typedef std::map<std::string, ElementTypeMapBase *> ElementalDataMap; typedef std::vector<std::string> StringVector; typedef std::map<std::string, TypeCode> TypeCodeMap; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshData(const ID & id = "mesh_data", const ID & parent_id = "", const MemoryID & memory_id = 0); ~MeshData(); /* ------------------------------------------------------------------------ */ /* Methods and accessors */ /* ------------------------------------------------------------------------ */ public: /// Register new elemental data (and alloc data) with check if the name is new template<typename T> void registerElementalData(const std::string & name); inline void registerElementalData(const std::string & name, TypeCode type); /// Get an existing elemental data array template<typename T> const Array<T> & getElementalDataArray(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type = _not_ghost) const; template<typename T> Array<T> & getElementalDataArray(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type = _not_ghost); /// Get an elemental data array, if it does not exist: allocate it template<typename T> Array<T> & getElementalDataArrayAlloc(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type = _not_ghost, UInt nb_component = 1); /// get the names of the data stored in elemental_data inline void getTagNames(StringVector & tags, const ElementType & type, const GhostType & ghost_type = _not_ghost) const; /// get the type of the data stored in elemental_data template<typename T> TypeCode getTypeCode() const; inline TypeCode getTypeCode(const std::string name) const; template<typename T> inline UInt getNbComponentTemplated(const std::string, const ElementType & el_type, const GhostType & ghost_type) const; inline UInt getNbComponent(const std::string name, const ElementType & el_type, const GhostType & ghost_type = _not_ghost) const; /// Get an existing elemental data template<typename T> const ElementTypeMapArray<T> & getElementalData(const std::string & name) const; template<typename T> ElementTypeMapArray<T> & getElementalData(const std::string & name); private: /// Register new elemental data (add alloc data) template<typename T> ElementTypeMapArray<T> * allocElementalData(const std::string & name); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// Map when elemental data is stored as ElementTypeMap ElementalDataMap elemental_data; /// Map when elementalType of the data stored in elemental_data TypeCodeMap typecode_map; }; #include "mesh_data_tmpl.hh" #undef AKANTU_MESH_DATA_TUPLE_FIRST_ELEM -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MESH_DATA_HH__ */ diff --git a/src/mesh/mesh_data_tmpl.hh b/src/mesh/mesh_data_tmpl.hh index 27343db0f..17fb098ac 100644 --- a/src/mesh/mesh_data_tmpl.hh +++ b/src/mesh/mesh_data_tmpl.hh @@ -1,218 +1,218 @@ /** * @file mesh_data_tmpl.hh * * @author Dana Christen <dana.christen@gmail.com> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri May 03 2013 * @date last modification: Thu Nov 05 2015 * * @brief Stores generic data loaded from the mesh file * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ -__END_AKANTU__ +} // akantu #include <iostream> #define MESH_DATA_GET_TYPE(r, data, type) \ template<> \ inline MeshDataTypeCode MeshData::getTypeCode<BOOST_PP_TUPLE_ELEM(2, 1, type)>() const { \ return BOOST_PP_TUPLE_ELEM(2, 0, type); \ } -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ // get the type of the data stored in elemental_data template<typename T> inline MeshDataTypeCode MeshData::getTypeCode() const { AKANTU_DEBUG_ERROR("Type " << debug::demangle(typeid(T).name()) << "not implemented by MeshData."); } /* -------------------------------------------------------------------------- */ BOOST_PP_SEQ_FOR_EACH(MESH_DATA_GET_TYPE, void, AKANTU_MESH_DATA_TYPES) #undef MESH_DATA_GET_TYPE inline MeshDataTypeCode MeshData::getTypeCode(const std::string name) const { TypeCodeMap::const_iterator it = typecode_map.find(name); if(it == typecode_map.end()) AKANTU_EXCEPTION("No dataset named " << name << " found."); return it->second; } /* -------------------------------------------------------------------------- */ // Register new elemental data templated (and alloc data) with check if the name is new template<typename T> void MeshData::registerElementalData(const std::string & name) { ElementalDataMap::iterator it = elemental_data.find(name); if(it == elemental_data.end()) { allocElementalData<T>(name); } else{ AKANTU_DEBUG_INFO("Data named " << name << " already registered."); } } /* -------------------------------------------------------------------------- */ // Register new elemental data of a given MeshDataTypeCode with check if the name is new #define AKANTU_MESH_DATA_CASE_MACRO(r, name, elem) \ case BOOST_PP_TUPLE_ELEM(2, 0, elem) : { registerElementalData<BOOST_PP_TUPLE_ELEM(2, 1, elem)>(name); break; } inline void MeshData::registerElementalData(const std::string & name, MeshDataTypeCode type) { switch(type) { BOOST_PP_SEQ_FOR_EACH(AKANTU_MESH_DATA_CASE_MACRO, name, AKANTU_MESH_DATA_TYPES) default : AKANTU_DEBUG_ERROR("Type " << type << "not implemented by MeshData."); } } #undef AKANTU_MESH_DATA_CASE_MACRO /* -------------------------------------------------------------------------- */ /// Register new elemental data (and alloc data) template<typename T> ElementTypeMapArray<T> * MeshData::allocElementalData(const std::string & name) { ElementTypeMapArray<T> * dataset = new ElementTypeMapArray<T>(name, id, memory_id); elemental_data[name] = dataset; typecode_map[name] = getTypeCode<T>(); return dataset; } /* -------------------------------------------------------------------------- */ template<typename T> const ElementTypeMapArray<T> & MeshData::getElementalData(const std::string & name) const { ElementalDataMap::const_iterator it = elemental_data.find(name); if(it == elemental_data.end()) AKANTU_EXCEPTION("No dataset named " << name << " found."); return dynamic_cast<const ElementTypeMapArray<T> &>(*(it->second)); } /* -------------------------------------------------------------------------- */ // Get an existing elemental data template<typename T> ElementTypeMapArray<T> & MeshData::getElementalData(const std::string & name) { ElementalDataMap::iterator it = elemental_data.find(name); if(it == elemental_data.end()) AKANTU_EXCEPTION("No dataset named " << name << " found."); return dynamic_cast<ElementTypeMapArray<T> &>(*(it->second)); } /* -------------------------------------------------------------------------- */ // Get an existing elemental data array for an element type template<typename T> const Array<T> & MeshData::getElementalDataArray(const std::string & name, const ElementType & elem_type, const GhostType & ghost_type) const { ElementalDataMap::const_iterator it = elemental_data.find(name); if(it == elemental_data.end()) { AKANTU_EXCEPTION("Data named " << name << " not registered for type: " << elem_type << " - ghost_type:" << ghost_type << "!"); } return dynamic_cast<const ElementTypeMapArray<T> &>(*(it->second))(elem_type, ghost_type); } template<typename T> Array<T> & MeshData::getElementalDataArray(const std::string & name, const ElementType & elem_type, const GhostType & ghost_type) { ElementalDataMap::iterator it = elemental_data.find(name); if(it == elemental_data.end()) { AKANTU_EXCEPTION("Data named " << name << " not registered for type: " << elem_type << " - ghost_type:" << ghost_type << "!"); } return dynamic_cast<ElementTypeMapArray<T> &>(*(it->second))(elem_type, ghost_type); } /* -------------------------------------------------------------------------- */ // Get an elemental data array, if it does not exist: allocate it template<typename T> Array<T> & MeshData::getElementalDataArrayAlloc(const std::string & name, const ElementType & elem_type, const GhostType & ghost_type, UInt nb_component) { ElementalDataMap::iterator it = elemental_data.find(name); ElementTypeMapArray<T> * dataset; if(it == elemental_data.end()) { dataset = allocElementalData<T>(name); } else { dataset = dynamic_cast<ElementTypeMapArray<T> *>(it->second); } AKANTU_DEBUG_ASSERT(getTypeCode<T>() == typecode_map.find(name)->second, "Function getElementalDataArrayAlloc called with the wrong type!"); if(!(dataset->exists(elem_type, ghost_type))) { dataset->alloc(0, nb_component, elem_type, ghost_type); } return (*dataset)(elem_type, ghost_type); } /* -------------------------------------------------------------------------- */ #define AKANTU_MESH_DATA_CASE_MACRO(r, name, elem) \ case BOOST_PP_TUPLE_ELEM(2, 0, elem) : { \ nb_comp = getNbComponentTemplated<BOOST_PP_TUPLE_ELEM(2, 1, elem)>(name, el_type, ghost_type); \ break; \ } \ inline UInt MeshData::getNbComponent(const std::string name, const ElementType & el_type, const GhostType & ghost_type) const { TypeCodeMap::const_iterator it = typecode_map.find(name); UInt nb_comp(0); if(it == typecode_map.end()) { AKANTU_EXCEPTION("Could not determine the type held in dataset " << name << " for type: " << el_type << " - ghost_type:" << ghost_type << "."); } MeshDataTypeCode type = it->second; switch(type) { BOOST_PP_SEQ_FOR_EACH(AKANTU_MESH_DATA_CASE_MACRO, name, AKANTU_MESH_DATA_TYPES) default : AKANTU_DEBUG_ERROR("Could not call the correct instance of getNbComponentTemplated."); break; } return nb_comp; } #undef AKANTU_MESH_DATA_CASE_MACRO /* -------------------------------------------------------------------------- */ template<typename T> inline UInt MeshData::getNbComponentTemplated(const std::string name, const ElementType & el_type, const GhostType & ghost_type) const { return getElementalDataArray<T>(name, el_type, ghost_type).getNbComponent(); } /* -------------------------------------------------------------------------- */ // get the names of the data stored in elemental_data #define AKANTU_MESH_DATA_CASE_MACRO(r, name, elem) \ case BOOST_PP_TUPLE_ELEM(2, 0, elem) : { \ ElementTypeMapArray<BOOST_PP_TUPLE_ELEM(2, 1, elem)> * dataset; \ dataset = dynamic_cast< ElementTypeMapArray<BOOST_PP_TUPLE_ELEM(2, 1, elem)> * >(it->second); \ exists = dataset->exists(el_type, ghost_type); \ break; \ } \ inline void MeshData::getTagNames(StringVector & tags, const ElementType & el_type, const GhostType & ghost_type) const { tags.clear(); bool exists(false); ElementalDataMap::const_iterator it = elemental_data.begin(); ElementalDataMap::const_iterator it_end = elemental_data.end(); for(; it != it_end; ++it) { MeshDataTypeCode type = getTypeCode(it->first); switch(type) { BOOST_PP_SEQ_FOR_EACH(AKANTU_MESH_DATA_CASE_MACRO, , AKANTU_MESH_DATA_TYPES) default : AKANTU_DEBUG_ERROR("Could not determine the proper type to (dynamic-)cast."); break; } if(exists) { tags.push_back(it->first); } } } #undef AKANTU_MESH_DATA_CASE_MACRO /* -------------------------------------------------------------------------- */ diff --git a/src/mesh/mesh_events.hh b/src/mesh/mesh_events.hh index 2a3fd8855..bb0cb2539 100644 --- a/src/mesh/mesh_events.hh +++ b/src/mesh/mesh_events.hh @@ -1,187 +1,187 @@ /** * @file mesh_events.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Feb 20 2015 * @date last modification: Mon Dec 07 2015 * * @brief Classes corresponding to mesh events type * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" #include "element.hh" #include "element_type_map.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_EVENTS_HH__ #define __AKANTU_MESH_EVENTS_HH__ -__BEGIN_AKANTU__ +namespace akantu { /// akantu::MeshEvent is the base event for meshes template <class Entity> class MeshEvent { public: virtual ~MeshEvent() {} /// Get the list of entity modified by the event nodes or elements const Array<Entity> & getList() const { return list; } /// Get the list of entity modified by the event nodes or elements Array<Entity> & getList() { return list; } protected: Array<Entity> list; }; class Mesh; /// akantu::MeshEvent related to new nodes in the mesh class NewNodesEvent : public MeshEvent<UInt> { public: virtual ~NewNodesEvent(){}; }; /// akantu::MeshEvent related to nodes removed from the mesh class RemovedNodesEvent : public MeshEvent<UInt> { public: virtual ~RemovedNodesEvent(){}; inline RemovedNodesEvent(const Mesh & mesh); /// Get the new numbering following suppression of nodes from nodes arrays AKANTU_GET_MACRO_NOT_CONST(NewNumbering, new_numbering, Array<UInt> &); /// Get the new numbering following suppression of nodes from nodes arrays AKANTU_GET_MACRO(NewNumbering, new_numbering, const Array<UInt> &); private: Array<UInt> new_numbering; }; /// akantu::MeshEvent related to new elements in the mesh class NewElementsEvent : public MeshEvent<Element> { public: virtual ~NewElementsEvent(){}; }; /// akantu::MeshEvent related to elements removed from the mesh class RemovedElementsEvent : public MeshEvent<Element> { public: virtual ~RemovedElementsEvent(){}; inline RemovedElementsEvent(const Mesh & mesh, ID new_numbering_id = "new_numbering"); /// Get the new numbering following suppression of elements from elements /// arrays AKANTU_GET_MACRO(NewNumbering, new_numbering, const ElementTypeMapArray<UInt> &); /// Get the new numbering following suppression of elements from elements /// arrays AKANTU_GET_MACRO_NOT_CONST(NewNumbering, new_numbering, ElementTypeMapArray<UInt> &); /// Get the new numbering following suppression of elements from elements /// arrays AKANTU_GET_MACRO_BY_ELEMENT_TYPE(NewNumbering, new_numbering, UInt); /// Get the new numbering following suppression of elements from elements /// arrays AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(NewNumbering, new_numbering, UInt); protected: ElementTypeMapArray<UInt> new_numbering; }; /// akantu::MeshEvent for element that changed in some sort, can be seen as a /// combination of removed and added elements class ChangedElementsEvent : public RemovedElementsEvent { public: virtual ~ChangedElementsEvent(){}; inline ChangedElementsEvent( const Mesh & mesh, ID new_numbering_id = "changed_event:new_numbering") : RemovedElementsEvent(mesh, new_numbering_id){}; AKANTU_GET_MACRO(ListOld, list, const Array<Element> &); AKANTU_GET_MACRO_NOT_CONST(ListOld, list, Array<Element> &); AKANTU_GET_MACRO(ListNew, new_list, const Array<Element> &); AKANTU_GET_MACRO_NOT_CONST(ListNew, new_list, Array<Element> &); protected: Array<Element> new_list; }; /* -------------------------------------------------------------------------- */ class MeshEventHandler { public: virtual ~MeshEventHandler(){}; /* ------------------------------------------------------------------------ */ /* Internal code */ /* ------------------------------------------------------------------------ */ private: /// send a akantu::NewNodesEvent inline void sendEvent(const NewNodesEvent & event) { onNodesAdded(event.getList(), event); } /// send a akantu::RemovedNodesEvent inline void sendEvent(const RemovedNodesEvent & event) { onNodesRemoved(event.getList(), event.getNewNumbering(), event); } /// send a akantu::NewElementsEvent inline void sendEvent(const NewElementsEvent & event) { onElementsAdded(event.getList(), event); } /// send a akantu::RemovedElementsEvent inline void sendEvent(const RemovedElementsEvent & event) { onElementsRemoved(event.getList(), event.getNewNumbering(), event); } /// send a akantu::ChangedElementsEvent inline void sendEvent(const ChangedElementsEvent & event) { onElementsChanged(event.getListOld(), event.getListNew(), event.getNewNumbering(), event); } template <class EventHandler> friend class EventHandlerManager; /* ------------------------------------------------------------------------ */ /* Interface */ /* ------------------------------------------------------------------------ */ public: /// function to implement to react on akantu::NewNodesEvent virtual void onNodesAdded(const Array<UInt> & nodes_list, const NewNodesEvent & event) = 0; /// function to implement to react on akantu::RemovedNodesEvent virtual void onNodesRemoved(const Array<UInt> & nodes_list, const Array<UInt> & new_numbering, const RemovedNodesEvent & event) = 0; /// function to implement to react on akantu::NewElementsEvent virtual void onElementsAdded(const Array<Element> & elements_list, const NewElementsEvent & event) = 0; /// function to implement to react on akantu::RemovedElementsEvent virtual void onElementsRemoved(const Array<Element> & elements_list, const ElementTypeMapArray<UInt> & new_numbering, const RemovedElementsEvent & event) = 0; /// function to implement to react on akantu::ChangedElementsEvent virtual void onElementsChanged(const Array<Element> & old_elements_list, const Array<Element> & new_elements_list, const ElementTypeMapArray<UInt> & new_numbering, const ChangedElementsEvent & event) = 0; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MESH_EVENTS_HH__ */ diff --git a/src/mesh/mesh_filter.hh b/src/mesh/mesh_filter.hh index fcd25618d..9b812fbe4 100644 --- a/src/mesh/mesh_filter.hh +++ b/src/mesh/mesh_filter.hh @@ -1,75 +1,75 @@ /** * @file mesh_filter.hh * * @author David Simon Kammer <david.kammer@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Dec 18 2015 * * @brief the class representing the meshes * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_FILTER_HH__ #define __AKANTU_MESH_FILTER_HH__ /* -------------------------------------------------------------------------- */ #include "element.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* Filter Functors */ /* -------------------------------------------------------------------------- */ /// struct for the possible filter functors struct FilterFunctor { enum Type { _node_filter_functor, _element_filter_functor }; }; /// class (functor) for the node filter class NodeFilterFunctor : public FilterFunctor { public: bool operator()(__attribute__((unused)) UInt node) { AKANTU_DEBUG_TO_IMPLEMENT(); } public: static const Type type = _node_filter_functor; }; /// class (functor) for the element filter class ElementFilterFunctor : public FilterFunctor { public: bool operator()(__attribute__((unused)) const Element & element) { AKANTU_DEBUG_TO_IMPLEMENT(); } public: static const Type type = _element_filter_functor; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MESH_FILTER_HH__ */ diff --git a/src/mesh/mesh_inline_impl.cc b/src/mesh/mesh_inline_impl.cc index 506027a8e..3e74a8532 100644 --- a/src/mesh/mesh_inline_impl.cc +++ b/src/mesh/mesh_inline_impl.cc @@ -1,630 +1,630 @@ /** * @file mesh_inline_impl.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Dana Christen <dana.christen@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Thu Jul 15 2010 * @date last modification: Thu Jan 21 2016 * * @brief Implementation of the inline functions of the mesh class * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #if defined(AKANTU_COHESIVE_ELEMENT) #include "cohesive_element.hh" #endif #ifndef __AKANTU_MESH_INLINE_IMPL_CC__ #define __AKANTU_MESH_INLINE_IMPL_CC__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ inline RemovedNodesEvent::RemovedNodesEvent(const Mesh & mesh) : new_numbering(mesh.getNbNodes(), 1, "new_numbering") {} /* -------------------------------------------------------------------------- */ inline RemovedElementsEvent::RemovedElementsEvent(const Mesh & mesh, ID new_numbering_id) : new_numbering(new_numbering_id, mesh.getID(), mesh.getMemoryID()) {} /* -------------------------------------------------------------------------- */ template <> inline void Mesh::sendEvent<RemovedElementsEvent>(RemovedElementsEvent & event) { this->connectivities.onElementsRemoved(event.getNewNumbering()); EventHandlerManager<MeshEventHandler>::sendEvent(event); } /* -------------------------------------------------------------------------- */ template <> inline void Mesh::sendEvent<RemovedNodesEvent>(RemovedNodesEvent & event) { if (created_nodes) this->removeNodesFromArray(*nodes, event.getNewNumbering()); if (nodes_global_ids) this->removeNodesFromArray(*nodes_global_ids, event.getNewNumbering()); if (nodes_type.getSize() != 0) this->removeNodesFromArray(nodes_type, event.getNewNumbering()); EventHandlerManager<MeshEventHandler>::sendEvent(event); } /* -------------------------------------------------------------------------- */ template <typename T> inline void Mesh::removeNodesFromArray(Array<T> & vect, const Array<UInt> & new_numbering) { Array<T> tmp(vect.getSize(), vect.getNbComponent()); UInt nb_component = vect.getNbComponent(); UInt new_nb_nodes = 0; for (UInt i = 0; i < new_numbering.getSize(); ++i) { UInt new_i = new_numbering(i); if (new_i != UInt(-1)) { T * to_copy = vect.storage() + i * nb_component; std::uninitialized_copy(to_copy, to_copy + nb_component, tmp.storage() + new_i * nb_component); ++new_nb_nodes; } } tmp.resize(new_nb_nodes); vect.copy(tmp); } /* -------------------------------------------------------------------------- */ inline UInt Mesh::elementToLinearized(const Element & elem) const { AKANTU_DEBUG_ASSERT(elem.type < _max_element_type && elem.element < types_offsets.storage()[elem.type + 1], "The element " << elem << "does not exists in the mesh " << getID()); return types_offsets.storage()[elem.type] + elem.element; } /* -------------------------------------------------------------------------- */ inline Element Mesh::linearizedToElement(UInt linearized_element) const { UInt t; for (t = _not_defined; t != _max_element_type && linearized_element >= types_offsets(t); ++t) ; AKANTU_DEBUG_ASSERT(linearized_element < types_offsets(t), "The linearized element " << linearized_element << "does not exists in the mesh " << getID()); --t; ElementType type = ElementType(t); return Element(type, linearized_element - types_offsets.storage()[t], _not_ghost, getKind(type)); } /* -------------------------------------------------------------------------- */ inline void Mesh::updateTypesOffsets(const GhostType & ghost_type) { Array<UInt> * types_offsets_ptr = &this->types_offsets; if (ghost_type == _ghost) types_offsets_ptr = &this->ghost_types_offsets; Array<UInt> & types_offsets = *types_offsets_ptr; types_offsets.clear(); for (auto type : elementTypes(_all_dimensions, ghost_type, _ek_not_defined)) types_offsets(type) = connectivities(type, ghost_type).getSize(); for (UInt t = _not_defined + 1; t < _max_element_type; ++t) types_offsets(t) += types_offsets(t - 1); for (UInt t = _max_element_type; t > _not_defined; --t) types_offsets(t) = types_offsets(t - 1); types_offsets(0) = 0; } /* -------------------------------------------------------------------------- */ inline const Mesh::ConnectivityTypeList & Mesh::getConnectivityTypeList(const GhostType & ghost_type) const { if (ghost_type == _not_ghost) return type_set; else return ghost_type_set; } /* -------------------------------------------------------------------------- */ inline Array<UInt> * Mesh::getNodesGlobalIdsPointer() { AKANTU_DEBUG_IN(); if (nodes_global_ids == NULL) { std::stringstream sstr; sstr << getID() << ":nodes_global_ids"; nodes_global_ids = &(alloc<UInt>(sstr.str(), nodes->getSize(), 1)); for (UInt i = 0; i < nodes->getSize(); ++i) { (*nodes_global_ids)(i) = i; } } AKANTU_DEBUG_OUT(); return nodes_global_ids; } /* -------------------------------------------------------------------------- */ inline Array<NodeType> * Mesh::getNodesTypePointer() { AKANTU_DEBUG_IN(); if (nodes_type.getSize() == 0) { nodes_type.resize(nodes->getSize()); nodes_type.set(_nt_normal); } AKANTU_DEBUG_OUT(); return &nodes_type; } /* -------------------------------------------------------------------------- */ inline Array<UInt> * Mesh::getConnectivityPointer(const ElementType & type, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); Array<UInt> * tmp; if (!connectivities.exists(type, ghost_type)) { UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); tmp = &(connectivities.alloc(0, nb_nodes_per_element, type, ghost_type)); AKANTU_DEBUG_INFO("The connectivity vector for the type " << type << " created"); if (ghost_type == _not_ghost) type_set.insert(type); else ghost_type_set.insert(type); updateTypesOffsets(ghost_type); } else { tmp = &connectivities(type, ghost_type); } AKANTU_DEBUG_OUT(); return tmp; } /* -------------------------------------------------------------------------- */ inline Array<std::vector<Element>> * Mesh::getElementToSubelementPointer(const ElementType & type, const GhostType & ghost_type) { Array<std::vector<Element>> * tmp = getDataPointer<std::vector<Element>>( "element_to_subelement", type, ghost_type, 1, true); return tmp; } /* -------------------------------------------------------------------------- */ inline Array<Element> * Mesh::getSubelementToElementPointer(const ElementType & type, const GhostType & ghost_type) { Array<Element> * tmp = getDataPointer<Element>( "subelement_to_element", type, ghost_type, getNbFacetsPerElement(type), true, is_mesh_facets); return tmp; } /* -------------------------------------------------------------------------- */ inline const Array<std::vector<Element>> & Mesh::getElementToSubelement(const ElementType & type, const GhostType & ghost_type) const { return getData<std::vector<Element>>("element_to_subelement", type, ghost_type); } /* -------------------------------------------------------------------------- */ inline Array<std::vector<Element>> & Mesh::getElementToSubelement(const ElementType & type, const GhostType & ghost_type) { return getData<std::vector<Element>>("element_to_subelement", type, ghost_type); } /* -------------------------------------------------------------------------- */ inline const Array<Element> & Mesh::getSubelementToElement(const ElementType & type, const GhostType & ghost_type) const { return getData<Element>("subelement_to_element", type, ghost_type); } /* -------------------------------------------------------------------------- */ inline Array<Element> & Mesh::getSubelementToElement(const ElementType & type, const GhostType & ghost_type) { return getData<Element>("subelement_to_element", type, ghost_type); } /* -------------------------------------------------------------------------- */ template <typename T> inline Array<T> * Mesh::getDataPointer(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type, UInt nb_component, bool size_to_nb_element, bool resize_with_parent) { Array<T> & tmp = mesh_data.getElementalDataArrayAlloc<T>( data_name, el_type, ghost_type, nb_component); if (size_to_nb_element) { if (resize_with_parent) tmp.resize(mesh_parent->getNbElement(el_type, ghost_type)); else tmp.resize(this->getNbElement(el_type, ghost_type)); } else { tmp.resize(0); } return &tmp; } /* -------------------------------------------------------------------------- */ template <typename T> inline const Array<T> & Mesh::getData(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type) const { return mesh_data.getElementalDataArray<T>(data_name, el_type, ghost_type); } /* -------------------------------------------------------------------------- */ template <typename T> inline Array<T> & Mesh::getData(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type) { return mesh_data.getElementalDataArray<T>(data_name, el_type, ghost_type); } /* -------------------------------------------------------------------------- */ template <typename T> inline const ElementTypeMapArray<T> & Mesh::getData(const std::string & data_name) const { return mesh_data.getElementalData<T>(data_name); } /* -------------------------------------------------------------------------- */ template <typename T> inline ElementTypeMapArray<T> & Mesh::getData(const std::string & data_name) { return mesh_data.getElementalData<T>(data_name); } /* -------------------------------------------------------------------------- */ template <typename T> inline ElementTypeMapArray<T> & Mesh::registerData(const std::string & data_name) { this->mesh_data.registerElementalData<T>(data_name); return this->getData<T>(data_name); } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbElement(const ElementType & type, const GhostType & ghost_type) const { try { const Array<UInt> & conn = connectivities(type, ghost_type); return conn.getSize(); } catch (...) { return 0; } } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbElement(const UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & kind) const { AKANTU_DEBUG_ASSERT(spatial_dimension <= 3 || spatial_dimension == UInt(-1), "spatial_dimension is " << spatial_dimension << " and is greater than 3 !"); UInt nb_element = 0; for (auto type : elementTypes(spatial_dimension, ghost_type, kind)) nb_element += getNbElement(type, ghost_type); return nb_element; } /* -------------------------------------------------------------------------- */ inline void Mesh::getBarycenter(UInt element, const ElementType & type, Real * barycenter, GhostType ghost_type) const { UInt * conn_val = getConnectivity(type, ghost_type).storage(); UInt nb_nodes_per_element = getNbNodesPerElement(type); Real * local_coord = new Real[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->storage() + conn_val[offset + n] * spatial_dimension, spatial_dimension * sizeof(Real)); } Math::barycenter(local_coord, nb_nodes_per_element, spatial_dimension, barycenter); delete[] local_coord; } /* -------------------------------------------------------------------------- */ inline void Mesh::getBarycenter(const Element & element, Vector<Real> & barycenter) const { getBarycenter(element.element, element.type, barycenter.storage(), element.ghost_type); } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbNodesPerElement(const ElementType & type) { UInt nb_nodes_per_element = 0; #define GET_NB_NODES_PER_ELEMENT(type) \ nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_NODES_PER_ELEMENT); #undef GET_NB_NODES_PER_ELEMENT return nb_nodes_per_element; } /* -------------------------------------------------------------------------- */ inline ElementType Mesh::getP1ElementType(const ElementType & type) { ElementType p1_type = _not_defined; #define GET_P1_TYPE(type) p1_type = ElementClass<type>::getP1ElementType() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_P1_TYPE); #undef GET_P1_TYPE return p1_type; } /* -------------------------------------------------------------------------- */ inline ElementKind Mesh::getKind(const ElementType & type) { ElementKind kind = _ek_not_defined; #define GET_KIND(type) kind = ElementClass<type>::getKind() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_KIND); #undef GET_KIND return kind; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getSpatialDimension(const ElementType & type) { UInt spatial_dimension = 0; #define GET_SPATIAL_DIMENSION(type) \ spatial_dimension = ElementClass<type>::getSpatialDimension() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_SPATIAL_DIMENSION); #undef GET_SPATIAL_DIMENSION return spatial_dimension; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbFacetTypes(const ElementType & type, __attribute__((unused)) UInt t) { UInt nb = 0; #define GET_NB_FACET_TYPE(type) nb = ElementClass<type>::getNbFacetTypes() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_FACET_TYPE); #undef GET_NB_FACET_TYPE return nb; } /* -------------------------------------------------------------------------- */ inline ElementType Mesh::getFacetType(const ElementType & type, UInt t) { ElementType surface_type = _not_defined; #define GET_FACET_TYPE(type) surface_type = ElementClass<type>::getFacetType(t) AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_FACET_TYPE); #undef GET_FACET_TYPE return surface_type; } /* -------------------------------------------------------------------------- */ inline VectorProxy<ElementType> Mesh::getAllFacetTypes(const ElementType & type) { #define GET_FACET_TYPE(type) \ UInt nb = ElementClass<type>::getNbFacetTypes(); \ ElementType * elt_ptr = \ const_cast<ElementType *>(ElementClass<type>::getFacetTypeInternal()); \ return VectorProxy<ElementType>(elt_ptr, nb); AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_FACET_TYPE); #undef GET_FACET_TYPE } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbFacetsPerElement(const ElementType & type) { AKANTU_DEBUG_IN(); UInt n_facet = 0; #define GET_NB_FACET(type) n_facet = ElementClass<type>::getNbFacetsPerElement() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_FACET); #undef GET_NB_FACET AKANTU_DEBUG_OUT(); return n_facet; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbFacetsPerElement(const ElementType & type, UInt t) { AKANTU_DEBUG_IN(); UInt n_facet = 0; #define GET_NB_FACET(type) \ n_facet = ElementClass<type>::getNbFacetsPerElement(t) AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_FACET); #undef GET_NB_FACET AKANTU_DEBUG_OUT(); return n_facet; } /* -------------------------------------------------------------------------- */ inline MatrixProxy<UInt> Mesh::getFacetLocalConnectivity(const ElementType & type, UInt t) { AKANTU_DEBUG_IN(); #define GET_FACET_CON(type) \ AKANTU_DEBUG_OUT(); \ return ElementClass<type>::getFacetLocalConnectivityPerElement(t) AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_FACET_CON); #undef GET_FACET_CON AKANTU_DEBUG_OUT(); return MatrixProxy<UInt>( nullptr, 0, 0); // This avoid a compilation warning but will certainly // also cause a segfault if reached } /* -------------------------------------------------------------------------- */ inline Matrix<UInt> Mesh::getFacetConnectivity(const Element & element, UInt t) const { AKANTU_DEBUG_IN(); Matrix<UInt> local_facets(getFacetLocalConnectivity(element.type, t), false); Matrix<UInt> facets(local_facets.rows(), local_facets.cols()); const Array<UInt> & conn = connectivities(element.type, element.ghost_type); for (UInt f = 0; f < facets.rows(); ++f) { for (UInt n = 0; n < facets.cols(); ++n) { facets(f, n) = conn(element.element, local_facets(f, n)); } } AKANTU_DEBUG_OUT(); return facets; } /* -------------------------------------------------------------------------- */ template <typename T> inline void Mesh::extractNodalValuesFromElement( const Array<T> & nodal_values, T * local_coord, UInt * connectivity, UInt n_nodes, UInt nb_degree_of_freedom) const { for (UInt n = 0; n < n_nodes; ++n) { memcpy(local_coord + n * nb_degree_of_freedom, nodal_values.storage() + connectivity[n] * nb_degree_of_freedom, nb_degree_of_freedom * sizeof(T)); } } /* -------------------------------------------------------------------------- */ inline void Mesh::addConnectivityType(const ElementType & type, const GhostType & ghost_type) { getConnectivityPointer(type, ghost_type); } /* -------------------------------------------------------------------------- */ inline bool Mesh::isPureGhostNode(UInt n) const { return nodes_type.getSize() ? (nodes_type(n) == _nt_pure_gost) : false; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isLocalOrMasterNode(UInt n) const { return nodes_type.getSize() ? (nodes_type(n) == _nt_master) || (nodes_type(n) == _nt_normal) : true; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isLocalNode(UInt n) const { return nodes_type.getSize() ? nodes_type(n) == _nt_normal : true; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isMasterNode(UInt n) const { return nodes_type.getSize() ? nodes_type(n) == _nt_master : false; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isSlaveNode(UInt n) const { return nodes_type.getSize() ? nodes_type(n) >= 0 : false; } /* -------------------------------------------------------------------------- */ inline NodeType Mesh::getNodeType(UInt local_id) const { return nodes_type.getSize() ? nodes_type(local_id) : _nt_normal; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNodeGlobalId(UInt local_id) const { return nodes_global_ids ? (*nodes_global_ids)(local_id) : local_id; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNodeLocalId(UInt global_id) const { AKANTU_DEBUG_ASSERT(nodes_global_ids != NULL, "The global ids are note set."); return nodes_global_ids->find(global_id); } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbGlobalNodes() const { return nodes_global_ids ? nb_global_nodes : nodes->getSize(); } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbNodesPerElementList(const Array<Element> & elements) { UInt nb_nodes_per_element = 0; UInt nb_nodes = 0; ElementType current_element_type = _not_defined; Array<Element>::const_iterator<Element> el_it = elements.begin(); Array<Element>::const_iterator<Element> el_end = elements.end(); for (; el_it != el_end; ++el_it) { const Element & el = *el_it; if (el.type != current_element_type) { current_element_type = el.type; nb_nodes_per_element = Mesh::getNbNodesPerElement(current_element_type); } nb_nodes += nb_nodes_per_element; } return nb_nodes; } /* -------------------------------------------------------------------------- */ inline Mesh & Mesh::getMeshFacets() { if (!this->mesh_facets) AKANTU_EXCEPTION( "No facet mesh is defined yet! check the buildFacets functions"); return *this->mesh_facets; } /* -------------------------------------------------------------------------- */ inline const Mesh & Mesh::getMeshFacets() const { if (!this->mesh_facets) AKANTU_EXCEPTION( "No facet mesh is defined yet! check the buildFacets functions"); return *this->mesh_facets; } /* -------------------------------------------------------------------------- */ inline const Mesh & Mesh::getMeshParent() const { if (!this->mesh_parent) AKANTU_EXCEPTION( "No parent mesh is defined! This is only valid in a mesh_facets"); return *this->mesh_parent; } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MESH_INLINE_IMPL_CC__ */ diff --git a/src/mesh/node_group.cc b/src/mesh/node_group.cc index 5bb93cec5..df513dd9e 100644 --- a/src/mesh/node_group.cc +++ b/src/mesh/node_group.cc @@ -1,111 +1,111 @@ /** * @file node_group.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Dec 08 2015 * * @brief Implementation of the node group * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "node_group.hh" #include "dumpable.hh" #include "dumpable_inline_impl.hh" #include "mesh.hh" #if defined(AKANTU_USE_IOHELPER) # include "dumper_paraview.hh" #endif /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ NodeGroup::NodeGroup(const std::string & name, const Mesh & mesh, const std::string & id, const MemoryID & memory_id) : Memory(id, memory_id), name(name), node_group(alloc<UInt>(std::string(this->id + ":nodes"), 0, 1))//, // mesh(mesh) { #if defined(AKANTU_USE_IOHELPER) this->registerDumper<DumperParaview>("paraview_" + name, name, true); this->getDumper().registerField("positions",new dumper::NodalField<Real,true>( mesh.getNodes(), 0, 0, &this->getNodes())); #endif } /* -------------------------------------------------------------------------- */ NodeGroup::~NodeGroup() {} /* -------------------------------------------------------------------------- */ void NodeGroup::empty() { node_group.resize(0); } /* -------------------------------------------------------------------------- */ void NodeGroup::optimize() { std::sort(node_group.begin(), node_group.end()); Array<UInt>::iterator<> end = std::unique(node_group.begin(), node_group.end()); node_group.resize(end - node_group.begin()); } /* -------------------------------------------------------------------------- */ void NodeGroup::append(const NodeGroup & other_group) { AKANTU_DEBUG_IN(); UInt nb_nodes = node_group.getSize(); /// append new nodes to current list node_group.resize(nb_nodes + other_group.node_group.getSize()); std::copy(other_group.node_group.begin(), other_group.node_group.end(), node_group.begin() + nb_nodes); optimize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void NodeGroup::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "NodeGroup [" << std::endl; stream << space << " + name: " << name << std::endl; node_group.printself(stream, indent + 1); stream << space << "]" << std::endl; } -__END_AKANTU__ +} // akantu diff --git a/src/mesh/node_group.hh b/src/mesh/node_group.hh index c783039e7..a1602815a 100644 --- a/src/mesh/node_group.hh +++ b/src/mesh/node_group.hh @@ -1,137 +1,137 @@ /** * @file node_group.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Dec 08 2015 * * @brief Node group definition * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_array.hh" #include "aka_memory.hh" #include "mesh_filter.hh" #include "dumpable.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NODE_GROUP_HH__ #define __AKANTU_NODE_GROUP_HH__ -__BEGIN_AKANTU__ +namespace akantu { class NodeGroup : public Memory, public Dumpable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NodeGroup(const std::string & name, const Mesh & mesh, const std::string & id = "node_group", const MemoryID & memory_id = 0); virtual ~NodeGroup(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: typedef Array<UInt>::const_iterator<UInt> const_node_iterator; /// empty the node group void empty(); /// iterator to the beginning of the node group inline const_node_iterator begin() const; /// iterator to the end of the node group inline const_node_iterator end() const; /// add a node and give the local position through an iterator inline const_node_iterator add(UInt node, bool check_for_duplicate = true); /// remove a node inline void remove(UInt node); /// remove duplicated nodes void optimize(); /// append a group to current one void append(const NodeGroup & other_group); /// apply a filter on current node group template <typename T> void applyNodeFilter(T & filter); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO_NOT_CONST(Nodes, node_group, Array<UInt> &); AKANTU_GET_MACRO(Nodes, node_group, const Array<UInt> &); AKANTU_GET_MACRO(Name, name, const std::string &); /// give the number of nodes in the current group inline UInt getSize() const; UInt * storage(){return node_group.storage();}; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// name of the group std::string name; /// list of nodes in the group Array<UInt> & node_group; /// reference to the mesh in question //const Mesh & mesh; }; /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const NodeGroup & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "node_group_inline_impl.cc" #endif /* __AKANTU_NODE_GROUP_HH__ */ diff --git a/src/mesh/node_group_inline_impl.cc b/src/mesh/node_group_inline_impl.cc index e3e0fe046..5a4a22330 100644 --- a/src/mesh/node_group_inline_impl.cc +++ b/src/mesh/node_group_inline_impl.cc @@ -1,102 +1,102 @@ /** * @file node_group_inline_impl.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Dec 08 2015 * * @brief Node group inline function definitions * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ inline NodeGroup::const_node_iterator NodeGroup::begin() const { return node_group.begin(); } /* -------------------------------------------------------------------------- */ inline NodeGroup::const_node_iterator NodeGroup::end() const { return node_group.end(); } /* -------------------------------------------------------------------------- */ inline NodeGroup::const_node_iterator NodeGroup::add(UInt node, bool check_for_duplicate) { if(check_for_duplicate) { const_node_iterator it = std::find(begin(), end(), node); if(it == node_group.end()) { node_group.push_back(node); return (node_group.end() - 1); } return it; } else { node_group.push_back(node); return (node_group.end() - 1); } } /* -------------------------------------------------------------------------- */ inline void NodeGroup::remove(UInt node) { Array<UInt>::iterator<> it = this->node_group.begin(); Array<UInt>::iterator<> end = this->node_group.end(); AKANTU_DEBUG_ASSERT(it != end, "The node group is empty!!"); for (; it != node_group.end(); ++it) { if (*it == node) { it = node_group.erase(it); } } AKANTU_DEBUG_ASSERT(it != end, "The node was not found!"); } /* -------------------------------------------------------------------------- */ inline UInt NodeGroup::getSize() const { return node_group.getSize(); } /* -------------------------------------------------------------------------- */ struct FilterFunctor; template <typename T> void NodeGroup::applyNodeFilter(T & filter) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(T::type == FilterFunctor::_node_filter_functor, "NodeFilter can only apply node filter functor"); Array<UInt>::iterator<> it = this->node_group.begin(); for (; it != node_group.end(); ++it) { /// filter == true -> keep node if (!filter(*it)) { it = node_group.erase(it); } } AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu diff --git a/src/mesh_utils/cohesive_element_inserter.cc b/src/mesh_utils/cohesive_element_inserter.cc index 7678abca9..c069c2639 100644 --- a/src/mesh_utils/cohesive_element_inserter.cc +++ b/src/mesh_utils/cohesive_element_inserter.cc @@ -1,438 +1,438 @@ /** * @file cohesive_element_inserter.cc * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Dec 04 2013 * @date last modification: Sun Oct 04 2015 * * @brief Cohesive element inserter functions * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <algorithm> #include <limits> #include "cohesive_element_inserter.hh" #include "element_group.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { CohesiveElementInserter::CohesiveElementInserter(Mesh & mesh, bool is_extrinsic, ElementSynchronizer * synchronizer, const ID & id) : id(id), mesh(mesh), mesh_facets(mesh.initMeshFacets()), insertion_facets("insertion_facets", id), insertion_limits(mesh.getSpatialDimension(), 2), check_facets("check_facets", id) { MeshUtils::buildAllFacets(mesh, mesh_facets, 0, synchronizer); init(is_extrinsic); } /* -------------------------------------------------------------------------- */ CohesiveElementInserter::~CohesiveElementInserter() { #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) delete global_ids_updater; #endif } /* -------------------------------------------------------------------------- */ void CohesiveElementInserter::init(bool is_extrinsic) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); MeshUtils::resetFacetToDouble(mesh_facets); /// initialize facet insertion array mesh_facets.initElementTypeMapArray(insertion_facets, 1, spatial_dimension - 1, false, _ek_regular, true); /// init insertion limits for (UInt dim = 0; dim < spatial_dimension; ++dim) { insertion_limits(dim, 0) = std::numeric_limits<Real>::max() * (-1.); insertion_limits(dim, 1) = std::numeric_limits<Real>::max(); } if (is_extrinsic) { mesh_facets.initElementTypeMapArray(check_facets, 1, spatial_dimension - 1); initFacetsCheck(); } #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) facet_synchronizer = NULL; global_ids_updater = NULL; #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void CohesiveElementInserter::initFacetsCheck() { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType facet_gt = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, facet_gt); Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1, facet_gt); for (; it != last; ++it) { ElementType facet_type = *it; Array<bool> & f_check = check_facets(facet_type, facet_gt); const Array< std::vector<Element> > & element_to_facet = mesh_facets.getElementToSubelement(facet_type, facet_gt); UInt nb_facet = element_to_facet.getSize(); f_check.resize(nb_facet); for (UInt f = 0; f < nb_facet; ++f) { if (element_to_facet(f)[1] == ElementNull || (element_to_facet(f)[0].ghost_type == _ghost && element_to_facet(f)[1].ghost_type == _ghost)) { f_check(f) = false; } else f_check(f) = true; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void CohesiveElementInserter::limitCheckFacets() { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); Vector<Real> bary_facet(spatial_dimension); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, ghost_type); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, ghost_type); for(; it != end; ++it) { ElementType type = *it; Array<bool> & f_check = check_facets(type, ghost_type); UInt nb_facet = mesh_facets.getNbElement(type, ghost_type); for (UInt f = 0; f < nb_facet; ++f) { if (f_check(f)) { mesh_facets.getBarycenter(f, type, bary_facet.storage(), ghost_type); UInt coord_in_limit = 0; while (coord_in_limit < spatial_dimension && bary_facet(coord_in_limit) > insertion_limits(coord_in_limit, 0) && bary_facet(coord_in_limit) < insertion_limits(coord_in_limit, 1)) ++coord_in_limit; if (coord_in_limit != spatial_dimension) f_check(f) = false; } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void CohesiveElementInserter::setLimit(SpacialDirection axis, Real first_limit, Real second_limit) { AKANTU_DEBUG_ASSERT(axis < mesh.getSpatialDimension(), "You are trying to limit insertion in a direction that doesn't exist"); insertion_limits(axis, 0) = std::min(first_limit, second_limit); insertion_limits(axis, 1) = std::max(first_limit, second_limit); } /* -------------------------------------------------------------------------- */ UInt CohesiveElementInserter::insertIntrinsicElements() { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); Vector<Real> bary_facet(spatial_dimension); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, ghost_type); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, ghost_type); for(; it != end; ++it) { const ElementType type_facet = *it; Array<bool> & f_insertion = insertion_facets(type_facet, ghost_type); Array<std::vector<Element> > & element_to_facet = mesh_facets.getElementToSubelement(type_facet, ghost_type); UInt nb_facet = mesh_facets.getNbElement(type_facet, ghost_type); for (UInt f = 0; f < nb_facet; ++f) { if (element_to_facet(f)[1] == ElementNull) continue; mesh_facets.getBarycenter(f, type_facet, bary_facet.storage(), ghost_type); UInt coord_in_limit = 0; while (coord_in_limit < spatial_dimension && bary_facet(coord_in_limit) > insertion_limits(coord_in_limit, 0) && bary_facet(coord_in_limit) < insertion_limits(coord_in_limit, 1)) ++coord_in_limit; if (coord_in_limit == spatial_dimension) f_insertion(f) = true; } } } AKANTU_DEBUG_OUT(); return insertElements(); } /* -------------------------------------------------------------------------- */ void CohesiveElementInserter::insertIntrinsicElements(std::string physname, UInt material_index) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); ElementTypeMapArray<UInt> * phys_data; try { phys_data = &(mesh_facets.getData<UInt>("physical_names")); } catch(...){ phys_data = &(mesh_facets.registerData<UInt>("physical_names")); mesh_facets.initElementTypeMapArray(*phys_data, 1, spatial_dimension-1, false, _ek_regular, true); } Vector<Real> bary_facet(spatial_dimension); mesh_facets.createElementGroup(physname); GhostType ghost_type = _not_ghost; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, ghost_type); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, ghost_type); for(; it != end; ++it) { const ElementType type_facet = *it; Array<bool> & f_insertion = insertion_facets(type_facet, ghost_type); Array<std::vector<Element> > & element_to_facet = mesh_facets.getElementToSubelement(type_facet, ghost_type); UInt nb_facet = mesh_facets.getNbElement(type_facet, ghost_type); UInt coord_in_limit = 0; ElementGroup & group = mesh.getElementGroup(physname); ElementGroup & group_facet = mesh_facets.getElementGroup(physname); Vector<Real> bary_physgroup(spatial_dimension); Real norm_bary; for(ElementGroup::const_element_iterator el_it(group.element_begin (type_facet, ghost_type)); el_it!= group.element_end(type_facet, ghost_type); ++el_it) { UInt e = *el_it; mesh.getBarycenter(e, type_facet, bary_physgroup.storage(), ghost_type); #ifndef AKANTU_NDEBUG bool find_a_partner = false; #endif norm_bary = bary_physgroup.norm(); Array<UInt> & material_id = (*phys_data)(type_facet, ghost_type); for (UInt f = 0; f < nb_facet; ++f) { if (element_to_facet(f)[1] == ElementNull) continue; mesh_facets.getBarycenter(f, type_facet, bary_facet.storage(), ghost_type); coord_in_limit = 0; while (coord_in_limit < spatial_dimension && (std::abs(bary_facet(coord_in_limit) - bary_physgroup(coord_in_limit))/norm_bary < Math::getTolerance())) ++coord_in_limit; if (coord_in_limit == spatial_dimension) { f_insertion(f) = true; #ifndef AKANTU_NDEBUG find_a_partner = true; #endif group_facet.add(type_facet, f, ghost_type,false); material_id(f) = material_index; break; } } AKANTU_DEBUG_ASSERT(find_a_partner, "The element nO " << e << " of physical group " << physname << " did not find its associated facet!" << " Try to decrease math tolerance. " << std::endl); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ UInt CohesiveElementInserter::insertElements(bool only_double_facets) { NewNodesEvent node_event; node_event.getList().extendComponentsInterlaced(2, 1); NewElementsEvent element_event; UInt nb_new_elements = MeshUtils::insertCohesiveElements(mesh, mesh_facets, insertion_facets, node_event.getList(), element_event.getList(), only_double_facets); UInt nb_new_nodes = node_event.getList().getSize(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (mesh.getNodesType().getSize()) { /// update nodes type updateNodesType(mesh, node_event); updateNodesType(mesh_facets, node_event); /// update global ids nb_new_nodes = this->updateGlobalIDs(node_event); /// compute total number of new elements StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); comm.allReduce(&nb_new_elements, 1, _so_sum); } #endif if (nb_new_nodes > 0) mesh.sendEvent(node_event); if (nb_new_elements > 0) { updateInsertionFacets(); mesh.updateTypesOffsets(_not_ghost); mesh.sendEvent(element_event); MeshUtils::resetFacetToDouble(mesh_facets); } #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (mesh.getNodesType().getSize()) { /// update global ids this->synchronizeGlobalIDs(node_event); } #endif return nb_new_elements; } /* -------------------------------------------------------------------------- */ void CohesiveElementInserter::updateInsertionFacets() { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType facet_gt = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, facet_gt); Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1, facet_gt); for (; it != last; ++it) { ElementType facet_type = *it; Array<bool> & ins_facets = insertion_facets(facet_type, facet_gt); // this is the extrinsic case if (check_facets.exists(facet_type, facet_gt)) { Array<bool> & f_check = check_facets(facet_type, facet_gt); UInt nb_facets = f_check.getSize(); for (UInt f = 0; f < ins_facets.getSize(); ++f) { if (ins_facets(f)) { ++nb_facets; ins_facets(f) = false; f_check(f) = false; } } f_check.resize(nb_facets); } // and this the intrinsic one else { ins_facets.resize(mesh_facets.getNbElement(facet_type, facet_gt)); ins_facets.set(false); } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void CohesiveElementInserter::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "CohesiveElementInserter [" << std::endl; stream << space << " + mesh [" << std::endl; mesh.printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + mesh_facets [" << std::endl; mesh_facets.printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << "]" << std::endl; } -__END_AKANTU__ +} // akantu diff --git a/src/mesh_utils/cohesive_element_inserter.hh b/src/mesh_utils/cohesive_element_inserter.hh index d64517497..5f343b633 100644 --- a/src/mesh_utils/cohesive_element_inserter.hh +++ b/src/mesh_utils/cohesive_element_inserter.hh @@ -1,209 +1,209 @@ /** * @file cohesive_element_inserter.hh * * @author Fabian Barras <fabian.barras@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Dec 04 2013 * @date last modification: Fri Oct 02 2015 * * @brief Cohesive element inserter * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_COHESIVE_ELEMENT_INSERTER_HH__ #define __AKANTU_COHESIVE_ELEMENT_INSERTER_HH__ /* -------------------------------------------------------------------------- */ #include <numeric> #include "data_accessor.hh" #include "mesh_utils.hh" #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) # include "global_ids_updater.hh" # include "facet_synchronizer.hh" #endif /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class CohesiveElementInserter : public DataAccessor { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: CohesiveElementInserter(Mesh & mesh, bool is_extrinsic = false, ElementSynchronizer * synchronizer = NULL, const ID & id = "cohesive_element_inserter"); virtual ~CohesiveElementInserter(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// init function void init(bool is_extrinsic); /// set range limitation for intrinsic cohesive element insertion void setLimit(SpacialDirection axis, Real first_limit, Real second_limit); /// insert intrinsic cohesive elements in a predefined range UInt insertIntrinsicElements(); /// preset insertion of intrinsic cohesive elements along /// a predefined group of facet and assign them a defined material index. /// insertElement() method has to be called to finalize insertion. void insertIntrinsicElements(std::string physname, UInt material_index); /// insert extrinsic cohesive elements (returns the number of new /// cohesive elements) UInt insertElements(bool only_double_facets = false); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /// limit check facets to match given insertion limits void limitCheckFacets(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) /// init parallel variables void initParallel(FacetSynchronizer * facet_synchronizer, ElementSynchronizer * element_synchronizer); #endif protected: /// init facets check void initFacetsCheck(); /// update facet insertion arrays after facets doubling void updateInsertionFacets(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) /// update nodes type and global ids for parallel simulations /// (locally, within each processor) UInt updateGlobalIDs(NewNodesEvent & node_event); /// synchronize the global ids among the processors in parallel simulations void synchronizeGlobalIDs(NewNodesEvent & node_event); /// update nodes type void updateNodesType(Mesh & mesh, NewNodesEvent & node_event); /// functions for parallel communications inline UInt getNbDataForElements(const Array<Element> & elements, SynchronizationTag tag) const; inline void packElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag) const; inline void unpackElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag); template<bool pack_mode> inline void packUnpackGlobalConnectivity(CommunicationBuffer & buffer, const Array<Element> & elements) const; template<bool pack_mode> inline void packUnpackGroupedInsertionData(CommunicationBuffer & buffer, const Array<Element> & elements) const; #endif /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO_NOT_CONST(InsertionFacetsByElement, insertion_facets, ElementTypeMapArray<bool> &); AKANTU_GET_MACRO(InsertionFacetsByElement, insertion_facets, const ElementTypeMapArray<bool> &); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(InsertionFacets, insertion_facets, bool); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(CheckFacets, check_facets, bool); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(CheckFacets, check_facets, bool); AKANTU_GET_MACRO(MeshFacets, mesh_facets, const Mesh &); AKANTU_GET_MACRO_NOT_CONST(MeshFacets, mesh_facets, Mesh &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// object id ID id; /// main mesh where to insert cohesive elements Mesh & mesh; /// mesh containing facets Mesh & mesh_facets; /// list of facets where to insert elements ElementTypeMapArray<bool> insertion_facets; /// limits for element insertion Array<Real> insertion_limits; /// vector containing facets in which extrinsic cohesive elements can be inserted ElementTypeMapArray<bool> check_facets; #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) /// facet synchronizer FacetSynchronizer * facet_synchronizer; /// global connectivity ids updater GlobalIdsUpdater * global_ids_updater; #endif }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) # include "cohesive_element_inserter_inline_impl.cc" #endif /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const CohesiveElementInserter & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_COHESIVE_ELEMENT_INSERTER_HH__ */ diff --git a/src/mesh_utils/global_ids_updater.cc b/src/mesh_utils/global_ids_updater.cc index a87489d75..92e86dd74 100644 --- a/src/mesh_utils/global_ids_updater.cc +++ b/src/mesh_utils/global_ids_updater.cc @@ -1,59 +1,59 @@ /** * @file global_ids_updater.cc * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Apr 13 2012 * @date last modification: Fri Oct 02 2015 * * @brief Functions of the GlobalIdsUpdater * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "global_ids_updater.hh" #include "mesh_utils.hh" #include "element_synchronizer.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { UInt GlobalIdsUpdater::updateGlobalIDs(UInt old_nb_nodes) { UInt total_nb_new_nodes = this->updateGlobalIDsLocally(old_nb_nodes); this->synchronizeGlobalIDs(); return total_nb_new_nodes; } UInt GlobalIdsUpdater::updateGlobalIDsLocally(UInt old_nb_nodes) { UInt total_nb_new_nodes = MeshUtils::updateLocalMasterGlobalConnectivity(mesh, old_nb_nodes); return total_nb_new_nodes; } void GlobalIdsUpdater::synchronizeGlobalIDs() { this->synchronizer->computeBufferSize(*this, _gst_giu_global_conn); this->synchronizer->asynchronousSynchronize(*this, _gst_giu_global_conn); this->synchronizer->waitEndSynchronize(*this, _gst_giu_global_conn); } -__END_AKANTU__ +} // akantu diff --git a/src/mesh_utils/global_ids_updater_inline_impl.cc b/src/mesh_utils/global_ids_updater_inline_impl.cc index 73132a490..4976cc9e0 100644 --- a/src/mesh_utils/global_ids_updater_inline_impl.cc +++ b/src/mesh_utils/global_ids_updater_inline_impl.cc @@ -1,132 +1,132 @@ /** * @file global_ids_updater_inline_impl.cc * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Oct 02 2015 * @date last modification: Sun Oct 04 2015 * * @brief Implementation of the inline functions of GlobalIdsUpdater * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "global_ids_updater.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_GLOBAL_IDS_UPDATER_INLINE_IMPL_CC__ #define __AKANTU_GLOBAL_IDS_UPDATER_INLINE_IMPL_CC__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ inline UInt GlobalIdsUpdater::getNbData(const Array<Element> & elements, const SynchronizationTag & tag) const { UInt size = 0; if (elements.getSize() == 0) return size; if (tag == _gst_giu_global_conn) size += Mesh::getNbNodesPerElementList(elements) * sizeof(UInt); return size; } /* -------------------------------------------------------------------------- */ inline void GlobalIdsUpdater::packData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) const { if (tag == _gst_giu_global_conn) packUnpackGlobalConnectivity<true>(buffer, elements); } /* -------------------------------------------------------------------------- */ inline void GlobalIdsUpdater::unpackData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) { if (tag == _gst_giu_global_conn) packUnpackGlobalConnectivity<false>(buffer, elements); } /* -------------------------------------------------------------------------- */ template <bool pack_mode> inline void GlobalIdsUpdater::packUnpackGlobalConnectivity( CommunicationBuffer & buffer, const Array<Element> & elements) const { AKANTU_DEBUG_IN(); ElementType current_element_type = _not_defined; GhostType current_ghost_type = _casper; Array<UInt>::const_vector_iterator conn_begin; UInt nb_nodes_per_elem = 0; UInt index; Array<UInt> & global_nodes_ids = mesh.getGlobalNodesIds(); Array<Element>::const_scalar_iterator it = elements.begin(); Array<Element>::const_scalar_iterator end = elements.end(); for (; it != end; ++it) { const Element & el = *it; if (el.type != current_element_type || el.ghost_type != current_ghost_type) { current_element_type = el.type; current_ghost_type = el.ghost_type; const Array<UInt> & connectivity = mesh.getConnectivity(current_element_type, current_ghost_type); nb_nodes_per_elem = connectivity.getNbComponent(); conn_begin = connectivity.begin(nb_nodes_per_elem); } /// get element connectivity const Vector<UInt> current_conn = conn_begin[el.element]; /// loop on all connectivity nodes for (UInt n = 0; n < nb_nodes_per_elem; ++n) { UInt node = current_conn(n); if (pack_mode) { /// if node is local or master pack its global id, otherwise /// dummy data if (mesh.isLocalOrMasterNode(node)) index = global_nodes_ids(node); else index = UInt(-1); buffer << index; } else { buffer >> index; /// update slave nodes' index if (index != UInt(-1) && mesh.isSlaveNode(node)) global_nodes_ids(node) = index; } } } AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_GLOBAL_IDS_UPDATER_INLINE_IMPL_CC__ */ diff --git a/src/mesh_utils/mesh_partition.cc b/src/mesh_utils/mesh_partition.cc index 27e60375a..648214182 100644 --- a/src/mesh_utils/mesh_partition.cc +++ b/src/mesh_utils/mesh_partition.cc @@ -1,441 +1,441 @@ /** * @file mesh_partition.cc * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Aug 17 2010 * @date last modification: Fri Jan 22 2016 * * @brief implementation of common part of all partitioner * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "mesh_partition.hh" #include "mesh_utils.hh" #include "aka_types.hh" /* -------------------------------------------------------------------------- */ #include <unordered_map> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ MeshPartition::MeshPartition(const Mesh & mesh, UInt spatial_dimension, const ID & id, const MemoryID & memory_id) : Memory(id, memory_id), mesh(mesh), spatial_dimension(spatial_dimension), partitions("partition", id, memory_id), ghost_partitions("ghost_partition", id, memory_id), ghost_partitions_offset("ghost_partition_offset", id, memory_id), saved_connectivity("saved_connectivity", id, memory_id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ MeshPartition::~MeshPartition() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * TODO this function should most probably be rewritten in a more modern way * conversion in c++ of the GENDUALMETIS (mesh.c) function wrote by George in * Metis (University of Minnesota) */ void MeshPartition::buildDualGraph(Array<Int> & dxadj, Array<Int> & dadjncy, Array<Int> & edge_loads, const EdgeLoadFunctor & edge_load_func) { AKANTU_DEBUG_IN(); // tweak mesh; const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); UInt nb_types = type_list.size(); UInt nb_good_types = 0; Vector<UInt> nb_nodes_per_element_p1(nb_types); Vector<UInt> magic_number(nb_types); // UInt * conn_val[nb_types]; Vector<UInt> nb_element(nb_types); Array<UInt> ** conn = new Array<UInt> *[nb_types]; Array<Element> lin_to_element; Element elem; elem.ghost_type = _not_ghost; const_cast<Mesh &>(mesh).updateTypesOffsets(_not_ghost); const_cast<Mesh &>(mesh).updateTypesOffsets(_ghost); 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; elem.type = type; ElementType type_p1 = Mesh::getP1ElementType(type); nb_nodes_per_element_p1[nb_good_types] = Mesh::getNbNodesPerElement(type_p1); nb_element[nb_good_types] = mesh.getConnectivity(type, _not_ghost).getSize(); magic_number[nb_good_types] = Mesh::getNbNodesPerElement(Mesh::getFacetType(type_p1)); conn[nb_good_types] = &const_cast<Array<UInt> &>(mesh.getConnectivity(type, _not_ghost)); for (UInt i = 0; i < nb_element[nb_good_types]; ++i) { elem.element = i; lin_to_element.push_back(elem); } nb_good_types++; } CSR<UInt> node_to_elem; MeshUtils::buildNode2Elements(mesh, node_to_elem); 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); /// 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(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(i) += dxadj(i - 1); for (UInt i = nb_total_element; i > 0; --i) dxadj(i) = dxadj(i - 1); dxadj(0) = 0; dadjncy.resize(2 * dxadj(nb_total_element)); edge_loads.resize(2 * dxadj(nb_total_element)); /// weight map to determine adjacency std::unordered_map<UInt, UInt> weight_map; for (UInt t = 0, linerized_el = 0; t < nb_good_types; ++t) { for (UInt el = 0; el < nb_element[t]; ++el, ++linerized_el) { /// fill the weight map for (UInt n = 0; n < nb_nodes_per_element_p1[t]; ++n) { UInt node = (*conn[t])(el, n); CSR<UInt>::iterator k; for (k = node_to_elem.rbegin(node); k != node_to_elem.rend(node); --k) { UInt current_el = *k; if (current_el <= linerized_el) break; auto it_w = weight_map.find(current_el); if (it_w == weight_map.end()) { weight_map[current_el] = 1; } else { it_w->second++; } } } /// each element with a weight of the size of a facet are adjacent for (auto 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; #if defined(AKANTU_COHESIVE_ELEMENT) /// Patch in order to prevent neighboring cohesive elements /// from detecting each other ElementKind linearized_el_kind = mesh.linearizedToElement(linerized_el).kind; ElementKind adjacent_el_kind = mesh.linearizedToElement(adjacent_el).kind; if (linearized_el_kind == adjacent_el_kind && linearized_el_kind == _ek_cohesive) continue; #endif UInt index_adj = dxadj(adjacent_el)++; UInt index_lin = dxadj(linerized_el)++; dadjncy(index_lin) = adjacent_el; dadjncy(index_adj) = linerized_el; } } 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(linerized_el); ++k, ++j) dadjncy(j) = dadjncy(k); dxadj(linerized_el) = j; k_start += nb_nodes_per_element_p1[t]; } for (UInt i = nb_total_element; i > 0; --i) dxadj(i) = dxadj(i - 1); dxadj(0) = 0; UInt adj = 0; for (UInt i = 0; i < nb_total_element; ++i) { UInt nb_adj = dxadj(i + 1) - dxadj(i); for (UInt j = 0; j < nb_adj; ++j, ++adj) { Int el_adj_id = dadjncy(dxadj(i) + j); Element el = lin_to_element(i); Element el_adj = lin_to_element(el_adj_id); Int load = edge_load_func(el, el_adj); edge_loads(adj) = load; } } delete [] conn; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshPartition::fillPartitionInformation( const Mesh & mesh, const Int * linearized_partitions) { AKANTU_DEBUG_IN(); CSR<UInt> node_to_elem; MeshUtils::buildNode2Elements(mesh, node_to_elem); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(spatial_dimension, _not_ghost, _ek_not_defined); UInt linearized_el = 0; for (; it != end; ++it) { ElementType type = *it; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); partitions.alloc(nb_element, 1, type, _not_ghost); CSR<UInt> & ghost_part_csr = ghost_partitions_csr(type, _not_ghost); ghost_part_csr.resizeRows(nb_element); ghost_partitions_offset.alloc(nb_element + 1, 1, type, _ghost); ghost_partitions.alloc(0, 1, type, _ghost); const Array<UInt> & connectivity = mesh.getConnectivity(type, _not_ghost); for (UInt el = 0; el < nb_element; ++el, ++linearized_el) { UInt part = linearized_partitions[linearized_el]; partitions(type, _not_ghost)(el) = part; std::list<UInt> list_adj_part; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity.storage()[el * nb_nodes_per_element + n]; CSR<UInt>::iterator ne; for (ne = node_to_elem.begin(node); ne != node_to_elem.end(node); ++ne) { UInt adj_el = *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<UInt>::iterator adj_it = list_adj_part.begin(); adj_it != list_adj_part.end(); ++adj_it) { ghost_part_csr.getRows().push_back(*adj_it); ghost_part_csr.rowOffset(el)++; ghost_partitions(type, _ghost).push_back(*adj_it); ghost_partitions_offset(type, _ghost)(el)++; } } ghost_part_csr.countToCSR(); /// convert the ghost_partitions_offset array in an offset array Array<UInt> & ghost_partitions_offset_ptr = ghost_partitions_offset(type, _ghost); for (UInt i = 1; i < nb_element; ++i) ghost_partitions_offset_ptr(i) += ghost_partitions_offset_ptr(i - 1); for (UInt i = nb_element; i > 0; --i) ghost_partitions_offset_ptr(i) = ghost_partitions_offset_ptr(i - 1); ghost_partitions_offset_ptr(0) = 0; } // All Facets for (Int sp = spatial_dimension - 1; sp >= 0; --sp) { Mesh::type_iterator fit = mesh.firstType(sp, _not_ghost, _ek_not_defined); Mesh::type_iterator fend = mesh.lastType(sp, _not_ghost, _ek_not_defined); for (; fit != fend; ++fit) { ElementType type = *fit; UInt nb_element = mesh.getNbElement(type); partitions.alloc(nb_element, 1, type, _not_ghost); AKANTU_DEBUG_INFO("Allocating partitions for " << type); CSR<UInt> & ghost_part_csr = ghost_partitions_csr(type, _not_ghost); ghost_part_csr.resizeRows(nb_element); ghost_partitions_offset.alloc(nb_element + 1, 1, type, _ghost); ghost_partitions.alloc(0, 1, type, _ghost); AKANTU_DEBUG_INFO("Allocating ghost_partitions for " << type); const Array<std::vector<Element> > & elem_to_subelem = mesh.getElementToSubelement(type, _not_ghost); for (UInt i(0); i < mesh.getNbElement(type, _not_ghost); ++i) { // Facet loop const std::vector<Element> & adjacent_elems = elem_to_subelem(i); if (!adjacent_elems.empty()) { Element min_elem; UInt min_part(std::numeric_limits<UInt>::max()); std::set<UInt> adjacent_parts; for (UInt j(0); j < adjacent_elems.size(); ++j) { UInt adjacent_elem_id = adjacent_elems[j].element; UInt adjacent_elem_part = partitions(adjacent_elems[j].type, adjacent_elems[j].ghost_type)(adjacent_elem_id); if (adjacent_elem_part < min_part) { min_part = adjacent_elem_part; min_elem = adjacent_elems[j]; } adjacent_parts.insert(adjacent_elem_part); } partitions(type, _not_ghost)(i) = min_part; CSR<UInt>::iterator git = ghost_partitions_csr(min_elem.type, _not_ghost) .begin(min_elem.element); CSR<UInt>::iterator gend = ghost_partitions_csr(min_elem.type, _not_ghost) .end(min_elem.element); for (; git != gend; ++git) { adjacent_parts.insert(*git); } adjacent_parts.erase(min_part); std::set<UInt>::const_iterator pit = adjacent_parts.begin(); std::set<UInt>::const_iterator pend = adjacent_parts.end(); for (; pit != pend; ++pit) { ghost_part_csr.getRows().push_back(*pit); ghost_part_csr.rowOffset(i)++; ghost_partitions(type, _ghost).push_back(*pit); } ghost_partitions_offset(type, _ghost)(i + 1) = ghost_partitions_offset(type, _ghost)(i + 1) + adjacent_elems.size(); } else { partitions(type, _not_ghost)(i) = 0; } } ghost_part_csr.countToCSR(); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshPartition::tweakConnectivity(const Array<UInt> & pairs) { AKANTU_DEBUG_IN(); if (pairs.getSize() == 0) return; Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(spatial_dimension, _not_ghost, _ek_not_defined); for (; it != end; ++it) { ElementType type = *it; Array<UInt> & conn = const_cast<Array<UInt> &>(mesh.getConnectivity(type, _not_ghost)); UInt nb_nodes_per_element = conn.getNbComponent(); UInt nb_element = conn.getSize(); Array<UInt> & saved_conn = saved_connectivity.alloc( nb_element, nb_nodes_per_element, type, _not_ghost); saved_conn.copy(conn); for (UInt i = 0; i < pairs.getSize(); ++i) { for (UInt el = 0; el < nb_element; ++el) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { if (pairs(i, 1) == conn(el, n)) conn(el, n) = pairs(i, 0); } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshPartition::restoreConnectivity() { AKANTU_DEBUG_IN(); ElementTypeMapArray<UInt>::type_iterator it = saved_connectivity.firstType( spatial_dimension, _not_ghost, _ek_not_defined); ElementTypeMapArray<UInt>::type_iterator end = saved_connectivity.lastType( spatial_dimension, _not_ghost, _ek_not_defined); for (; it != end; ++it) { ElementType type = *it; Array<UInt> & conn = const_cast<Array<UInt> &>(mesh.getConnectivity(type, _not_ghost)); Array<UInt> & saved_conn = saved_connectivity(type, _not_ghost); conn.copy(saved_conn); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/mesh_utils/mesh_partition.hh b/src/mesh_utils/mesh_partition.hh index 600f73ee4..849530369 100644 --- a/src/mesh_utils/mesh_partition.hh +++ b/src/mesh_utils/mesh_partition.hh @@ -1,150 +1,150 @@ /** * @file mesh_partition.hh * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Sep 01 2015 * * @brief tools to partitionate a mesh * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_PARTITION_HH__ #define __AKANTU_MESH_PARTITION_HH__ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" #include "aka_csr.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class MeshPartition : protected Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshPartition(const Mesh & mesh, UInt spatial_dimension, const ID & id = "MeshPartitioner", const MemoryID & memory_id = 0); virtual ~MeshPartition(); class EdgeLoadFunctor { public: virtual Int operator()(__attribute__((unused)) const Element & el1, __attribute__((unused)) const Element & el2) const = 0; }; class ConstEdgeLoadFunctor : public EdgeLoadFunctor { public: virtual inline Int operator()(__attribute__((unused)) const Element & el1, __attribute__((unused)) const Element & el2) const { return 1; } }; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// define a partition of the mesh virtual void partitionate(UInt nb_part, const EdgeLoadFunctor & edge_load_func = ConstEdgeLoadFunctor(), const Array<UInt> & pairs = Array<UInt>()) = 0; /// reorder the nodes to reduce the filling during the factorization of a /// matrix that has a profil based on the connectivity of the mesh virtual void reorder() = 0; /// fill the partitions array with a given linearized partition information void fillPartitionInformation(const Mesh & mesh, const Int * linearized_partitions); protected: /// build the dual graph of the mesh, for all element of spatial_dimension void buildDualGraph(Array<Int> & dxadj, Array<Int> & dadjncy, Array<Int> & edge_loads, const EdgeLoadFunctor & edge_load_func); /// tweak the mesh to handle the PBC pairs void tweakConnectivity(const Array<UInt> & pairs); /// restore the mesh that has been tweaked void restoreConnectivity(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(Partitions, partitions, const ElementTypeMapArray<UInt> &); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Partition, partitions, UInt); AKANTU_GET_MACRO(GhostPartitionCSR, ghost_partitions_csr, const ElementTypeMap< CSR<UInt> > &); AKANTU_GET_MACRO(NbPartition, nb_partitions, UInt); AKANTU_SET_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 ElementTypeMapArray<UInt> partitions; ElementTypeMap< CSR<UInt> > ghost_partitions_csr; ElementTypeMapArray<UInt> ghost_partitions; ElementTypeMapArray<UInt> ghost_partitions_offset; Array<UInt> * permutation; ElementTypeMapArray<UInt> saved_connectivity; }; -__END_AKANTU__ +} // akantu #ifdef AKANTU_USE_SCOTCH #include "mesh_partition_scotch.hh" #endif #endif /* __AKANTU_MESH_PARTITION_HH__ */ diff --git a/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.cc b/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.cc index 5665b17fa..1088437c9 100644 --- a/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.cc +++ b/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.cc @@ -1,141 +1,141 @@ /** * @file mesh_partition_mesh_data.cc * * @author Dana Christen <dana.christen@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * * @date creation: Fri May 03 2013 * @date last modification: Wed Nov 11 2015 * * @brief implementation of the MeshPartitionMeshData class * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "mesh_partition_mesh_data.hh" #if !defined(AKANTU_NDEBUG) #include <set> #endif /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ MeshPartitionMeshData::MeshPartitionMeshData(const Mesh & mesh, UInt spatial_dimension, const ID & id, const MemoryID & memory_id) : MeshPartition(mesh, spatial_dimension, id, memory_id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ MeshPartitionMeshData::MeshPartitionMeshData( const Mesh & mesh, const ElementTypeMapArray<UInt> & mapping, UInt spatial_dimension, const ID & id, const MemoryID & memory_id) : MeshPartition(mesh, spatial_dimension, id, memory_id), partition_mapping(&mapping) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshPartitionMeshData::partitionate(UInt nb_part, __attribute__((unused)) const EdgeLoadFunctor & edge_load_func, const Array<UInt> & pairs) { AKANTU_DEBUG_IN(); tweakConnectivity(pairs); nb_partitions = nb_part; GhostType ghost_type = _not_ghost; UInt spatial_dimension = mesh.getSpatialDimension(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type, _ek_not_defined); UInt linearized_el = 0; UInt nb_elements = mesh.getNbElement(mesh.getSpatialDimension(), ghost_type); Int * partition_list = new Int[nb_elements]; #if !defined(AKANTU_NDEBUG) std::set<UInt> partitions; #endif for (; it != end; ++it) { ElementType type = *it; const Array<UInt> & partition_array = (*partition_mapping)(type, ghost_type); Array<UInt>::const_iterator<Vector<UInt> > p_it = partition_array.begin(1); Array<UInt>::const_iterator<Vector<UInt> > p_end = partition_array.end(1); AKANTU_DEBUG_ASSERT(UInt(p_end - p_it) == mesh.getNbElement(type, ghost_type), "The partition mapping does not have the right number " << "of entries for type " << type << " and ghost type " << ghost_type << "." << " Tags=" << p_end - p_it << " Mesh=" << mesh.getNbElement(type, ghost_type)); for (; p_it != p_end; ++p_it, ++linearized_el) { partition_list[linearized_el] = (*p_it)(0); #if !defined(AKANTU_NDEBUG) partitions.insert((*p_it)(0)); #endif } } #if !defined(AKANTU_NDEBUG) AKANTU_DEBUG_ASSERT(partitions.size() == nb_part, "The number of real partitions does not match with the " "number of asked partitions"); #endif fillPartitionInformation(mesh, partition_list); delete[] partition_list; restoreConnectivity(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshPartitionMeshData::reorder() { AKANTU_DEBUG_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ void MeshPartitionMeshData::setPartitionMapping( const ElementTypeMapArray<UInt> & mapping) { partition_mapping = &mapping; } /* -------------------------------------------------------------------------- */ void MeshPartitionMeshData::setPartitionMappingFromMeshData( const std::string & data_name) { partition_mapping = &(mesh.getData<UInt>(data_name)); } -__END_AKANTU__ +} // akantu diff --git a/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.hh b/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.hh index aab69b9e5..bfb340547 100644 --- a/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.hh +++ b/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.hh @@ -1,98 +1,98 @@ /** * @file mesh_partition_mesh_data.hh * * @author Dana Christen <dana.christen@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief mesh partitioning based on data provided in the mesh * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_PARTITION_MESH_DATA_HH__ #define __AKANTU_MESH_PARTITION_MESH_DATA_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh_partition.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class MeshPartitionMeshData : public MeshPartition { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshPartitionMeshData(const Mesh & mesh, UInt spatial_dimension, const ID & id = "MeshPartitionerMeshData", const MemoryID & memory_id = 0); MeshPartitionMeshData(const Mesh & mesh, const ElementTypeMapArray<UInt> & mapping, UInt spatial_dimension, const ID & id = "MeshPartitionerMeshData", const MemoryID & memory_id = 0); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void partitionate(UInt nb_part, const EdgeLoadFunctor & edge_load_func = ConstEdgeLoadFunctor(), const Array<UInt> & pairs = Array<UInt>()); virtual void reorder(); void setPartitionMapping(const ElementTypeMapArray<UInt> & mapping); void setPartitionMappingFromMeshData(const std::string & data_name); private: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: const ElementTypeMapArray<UInt> * partition_mapping; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MESH_PARTITION_MESH_DATA_HH__ */ diff --git a/src/mesh_utils/mesh_partition/mesh_partition_scotch.cc b/src/mesh_utils/mesh_partition/mesh_partition_scotch.cc index eb6195dd8..7ba52fd3c 100644 --- a/src/mesh_utils/mesh_partition/mesh_partition_scotch.cc +++ b/src/mesh_utils/mesh_partition/mesh_partition_scotch.cc @@ -1,478 +1,478 @@ /** * @file mesh_partition_scotch.cc * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Jan 22 2016 * * @brief implementation of the MeshPartitionScotch class * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdio> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh_partition_scotch.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ #if !defined(AKANTU_USE_PTSCOTCH) #ifndef AKANTU_SCOTCH_NO_EXTERN extern "C" { #endif // AKANTU_SCOTCH_NO_EXTERN #include <scotch.h> #ifndef AKANTU_SCOTCH_NO_EXTERN } #endif // AKANTU_SCOTCH_NO_EXTERN #else // AKANTU_USE_PTSCOTCH #include <ptscotch.h> #endif // AKANTU_USE_PTSCOTCH -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ MeshPartitionScotch::MeshPartitionScotch(const Mesh & mesh, UInt spatial_dimension, const ID & id, const MemoryID & memory_id) : MeshPartition(mesh, spatial_dimension, id, memory_id) { AKANTU_DEBUG_IN(); // check if the akantu types and Scotch one are consistent #if __cplusplus > 199711L static_assert(sizeof(Int) == sizeof(SCOTCH_Num), "The integer type of Akantu does not match the one from Scotch"); #else AKANTU_DEBUG_ASSERT( sizeof(Int) == sizeof(SCOTCH_Num), "The integer type of Akantu does not match the one from Scotch"); #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ static SCOTCH_Mesh * createMesh(const Mesh & mesh) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes = mesh.getNbNodes(); UInt total_nb_element = 0; UInt nb_edge = 0; Mesh::type_iterator it = mesh.firstType(spatial_dimension); Mesh::type_iterator end = mesh.lastType(spatial_dimension); for (; it != end; ++it) { ElementType type = *it; 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)); it = mesh.firstType(spatial_dimension); for (; it != 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 Array<UInt> & 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.storage() + 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; it = mesh.firstType(spatial_dimension); for (; it != end; ++it) { ElementType type = *it; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); const Array<UInt> & connectivity = mesh.getConnectivity(type, _not_ghost); for (UInt el = 0; el < nb_element; ++el, ++linearized_el) { UInt * conn_val = connectivity.storage() + 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]; it = mesh.firstType(spatial_dimension); for (; it != end; ++it) { ElementType type = *it; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); const Array<UInt> & 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.storage() + 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 Array<Real> & nodes = mesh.getNodes(); Real * nodes_val = nodes.storage(); 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; } /* -------------------------------------------------------------------------- */ static void 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, const EdgeLoadFunctor & edge_load_func, const Array<UInt> & pairs) { AKANTU_DEBUG_IN(); nb_partitions = nb_part; tweakConnectivity(pairs); AKANTU_DEBUG_INFO("Partitioning the mesh " << mesh.getID() << " in " << nb_part << " parts."); Array<Int> dxadj; Array<Int> dadjncy; Array<Int> edge_loads; buildDualGraph(dxadj, dadjncy, edge_loads, edge_load_func); /// 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(vertnbr); // twice the number of "edges" //(an "edge" bounds two nodes) SCOTCH_Num * verttab = dxadj.storage(); // 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 = edge_loads.storage(); // integer load associated with // every edge ( optional ) SCOTCH_Num * edgetab = dadjncy.storage(); // 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 Array<Real> & nodes = mesh.getNodes(); Mesh::type_iterator f_it = mesh.firstType(spatial_dimension, _not_ghost, _ek_not_defined); Mesh::type_iterator f_end = mesh.lastType(spatial_dimension, _not_ghost, _ek_not_defined); Array<Real>::const_vector_iterator nodes_it = nodes.begin(spatial_dimension); UInt out_linerized_el = 0; for (; f_it != f_end; ++f_it) { ElementType type = *f_it; UInt nb_element = mesh.getNbElement(*f_it); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); const Array<UInt> & connectivity = mesh.getConnectivity(type); Vector<Real> mid(spatial_dimension); for (UInt el = 0; el < nb_element; ++el) { mid.set(0.); for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity.storage()[nb_nodes_per_element * el + n]; mid += Vector<Real>(nodes_it[node]); } mid /= 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); fillPartitionInformation(mesh, parttab); delete[] parttab; restoreConnectivity(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshPartitionScotch::reorder() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Reordering the mesh " << mesh.getID()); SCOTCH_Mesh * scotch_mesh = createMesh(mesh); 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(); for (UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType)g; Mesh::type_iterator it = mesh.firstType(_all_dimensions, gt); Mesh::type_iterator end = mesh.lastType(_all_dimensions, gt); for (; it != end; ++it) { ElementType type = *it; UInt nb_element = mesh.getNbElement(type, gt); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); const Array<UInt> & connectivity = mesh.getConnectivity(type, gt); UInt * conn = connectivity.storage(); 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().storage(); 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__ +} // akantu diff --git a/src/mesh_utils/mesh_partition/mesh_partition_scotch.hh b/src/mesh_utils/mesh_partition/mesh_partition_scotch.hh index 56fd76021..81eb819b3 100644 --- a/src/mesh_utils/mesh_partition/mesh_partition_scotch.hh +++ b/src/mesh_utils/mesh_partition/mesh_partition_scotch.hh @@ -1,81 +1,81 @@ /** * @file mesh_partition_scotch.hh * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief mesh partitioning based on libScotch * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_PARTITION_SCOTCH_HH__ #define __AKANTU_MESH_PARTITION_SCOTCH_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh_partition.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class MeshPartitionScotch : public MeshPartition { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshPartitionScotch(const Mesh & mesh, UInt spatial_dimension, const ID & id = "mesh_partition_scotch", const MemoryID & memory_id = 0); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void partitionate(UInt nb_part, const EdgeLoadFunctor & edge_load_func = ConstEdgeLoadFunctor(), const Array<UInt> & pairs = Array<UInt>()); virtual void reorder(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MESH_PARTITION_SCOTCH_HH__ */ diff --git a/src/mesh_utils/mesh_utils.cc b/src/mesh_utils/mesh_utils.cc index ff5862672..6bda16b0e 100644 --- a/src/mesh_utils/mesh_utils.cc +++ b/src/mesh_utils/mesh_utils.cc @@ -1,2369 +1,2369 @@ /** * @file mesh_utils.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Dana Christen <dana.christen@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Aug 20 2010 * @date last modification: Fri Jan 22 2016 * * @brief All mesh utils necessary for various tasks * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "mesh_utils.hh" #include "element_synchronizer.hh" #include "fe_engine.hh" #include "mesh_accessor.hh" /* -------------------------------------------------------------------------- */ #include <limits> #include <numeric> #include <queue> #include <set> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ void MeshUtils::buildNode2Elements(const Mesh & mesh, CSR<Element> & node_to_elem, UInt spatial_dimension) { AKANTU_DEBUG_IN(); if (spatial_dimension == _all_dimensions) spatial_dimension = mesh.getSpatialDimension(); /// count number of occurrence of each node UInt nb_nodes = mesh.getNbNodes(); /// array for the node-element list node_to_elem.resizeRows(nb_nodes); node_to_elem.clearRows(); AKANTU_DEBUG_ASSERT( mesh.firstType(spatial_dimension) != mesh.lastType(spatial_dimension), "Some elements must be found in right dimension to compute facets!"); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { Mesh::type_iterator first = mesh.firstType(spatial_dimension, *gt, _ek_not_defined); Mesh::type_iterator last = mesh.lastType(spatial_dimension, *gt, _ek_not_defined); for (; first != last; ++first) { ElementType type = *first; UInt nb_element = mesh.getNbElement(type, *gt); Array<UInt>::const_iterator<Vector<UInt>> conn_it = mesh.getConnectivity(type, *gt).begin( Mesh::getNbNodesPerElement(type)); for (UInt el = 0; el < nb_element; ++el, ++conn_it) for (UInt n = 0; n < conn_it->size(); ++n) ++node_to_elem.rowOffset((*conn_it)(n)); } } node_to_elem.countToCSR(); node_to_elem.resizeCols(); /// rearrange element to get the node-element list Element e; node_to_elem.beginInsertions(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { Mesh::type_iterator first = mesh.firstType(spatial_dimension, *gt, _ek_not_defined); Mesh::type_iterator last = mesh.lastType(spatial_dimension, *gt, _ek_not_defined); e.ghost_type = *gt; for (; first != last; ++first) { ElementType type = *first; e.type = type; e.kind = Mesh::getKind(type); UInt nb_element = mesh.getNbElement(type, *gt); Array<UInt>::const_iterator<Vector<UInt>> conn_it = mesh.getConnectivity(type, *gt).begin( Mesh::getNbNodesPerElement(type)); for (UInt el = 0; el < nb_element; ++el, ++conn_it) { e.element = el; for (UInt n = 0; n < conn_it->size(); ++n) node_to_elem.insertInRow((*conn_it)(n), e); } } } node_to_elem.endInsertions(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * This function should disappear in the future (used in mesh partitioning) */ void MeshUtils::buildNode2Elements(const Mesh & mesh, CSR<UInt> & node_to_elem, UInt spatial_dimension) { AKANTU_DEBUG_IN(); if (spatial_dimension == _all_dimensions) 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; Vector<UInt> nb_nodes_per_element(nb_types); UInt ** conn_val = new UInt *[nb_types]; Vector<UInt> nb_element(nb_types); 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); conn_val[nb_good_types] = mesh.getConnectivity(type, _not_ghost).storage(); 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(); /// count number of occurrence of each node 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_to_elem.countToCSR(); node_to_elem.resizeCols(); node_to_elem.beginInsertions(); /// rearrange element to get the node-element list 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.endInsertions(); delete[] conn_val; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildNode2ElementsElementTypeMap(const Mesh & mesh, CSR<UInt> & node_to_elem, const ElementType & type, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_elements = mesh.getConnectivity(type, ghost_type).getSize(); UInt * conn_val = mesh.getConnectivity(type, ghost_type).storage(); /// array for the node-element list node_to_elem.resizeRows(nb_nodes); node_to_elem.clearRows(); /// 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]); } /// convert the occurrence array in a csr one node_to_elem.countToCSR(); node_to_elem.resizeCols(); node_to_elem.beginInsertions(); /// save the element index in the node-element list 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.endInsertions(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildFacets(Mesh & mesh) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh.lastType(spatial_dimension - 1, gt_facet); for (; it != end; ++it) { mesh.getConnectivity(*it, *gt).resize(0); // \todo inform the mesh event handler } } buildFacetsDimension(mesh, mesh, true, spatial_dimension); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildAllFacets(const Mesh & mesh, Mesh & mesh_facets, UInt to_dimension) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); buildAllFacets(mesh, mesh_facets, spatial_dimension, to_dimension); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildAllFacets(const Mesh & mesh, Mesh & mesh_facets, UInt from_dimension, UInt to_dimension) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT( mesh_facets.isMeshFacets(), "The mesh_facets should be initialized with initMeshFacets"); const ElementTypeMapArray<UInt> * prank_to_element = nullptr; if (mesh.isDistributed()) { prank_to_element = &(mesh.getElementSynchronizer().getPrankToElement()); } /// generate facets buildFacetsDimension(mesh, mesh_facets, false, from_dimension, prank_to_element); /// copy nodes type MeshAccessor mesh_accessor_facets(mesh_facets); mesh_accessor_facets.getNodesType().copy(mesh.getNodesType()); /// sort facets and generate sub-facets for (UInt i = from_dimension - 1; i > to_dimension; --i) { buildFacetsDimension(mesh_facets, mesh_facets, false, i, prank_to_element); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildFacetsDimension( const Mesh & mesh, Mesh & mesh_facets, bool boundary_only, UInt dimension, const ElementTypeMapArray<UInt> * prank_to_element) { AKANTU_DEBUG_IN(); // save the current parent of mesh_facets and set it temporarly to mesh since // mesh is the one containing the elements for which mesh_facets has the // sub-elements // example: if the function is called with mesh = mesh_facets const Mesh * mesh_facets_parent = nullptr; try { mesh_facets_parent = &mesh_facets.getMeshParent(); } catch (...) { } mesh_facets.defineMeshParent(mesh); MeshAccessor mesh_accessor(mesh_facets); UInt spatial_dimension = mesh.getSpatialDimension(); const Array<Real> & mesh_facets_nodes = mesh_facets.getNodes(); const Array<Real>::const_vector_iterator mesh_facets_nodes_it = mesh_facets_nodes.begin(spatial_dimension); CSR<Element> node_to_elem; buildNode2Elements(mesh, node_to_elem, dimension); Array<UInt> counter; std::vector<Element> connected_elements; // init the SubelementToElement data to improve performance for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Mesh::type_iterator first = mesh.firstType(dimension, ghost_type); Mesh::type_iterator last = mesh.lastType(dimension, ghost_type); for (; first != last; ++first) { ElementType type = *first; mesh_accessor.getSubelementToElement(type, ghost_type); Vector<ElementType> facet_types = mesh.getAllFacetTypes(type); for (UInt ft = 0; ft < facet_types.size(); ++ft) { ElementType facet_type = facet_types(ft); mesh_accessor.getElementToSubelement(facet_type, ghost_type); mesh_accessor.getConnectivity(facet_type, ghost_type); } } } Element current_element; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; GhostType facet_ghost_type = ghost_type; current_element.ghost_type = ghost_type; Mesh::type_iterator first = mesh.firstType(dimension, ghost_type); Mesh::type_iterator last = mesh.lastType(dimension, ghost_type); for (; first != last; ++first) { ElementType type = *first; Vector<ElementType> facet_types = mesh.getAllFacetTypes(type); current_element.type = type; for (UInt ft = 0; ft < facet_types.size(); ++ft) { ElementType facet_type = facet_types(ft); UInt nb_element = mesh.getNbElement(type, ghost_type); Array<std::vector<Element>> * element_to_subelement = &mesh_facets.getElementToSubelement(facet_type, ghost_type); Array<UInt> * connectivity_facets = &mesh_facets.getConnectivity(facet_type, ghost_type); UInt nb_facet_per_element = mesh.getNbFacetsPerElement(type, ft); const Array<UInt> & element_connectivity = mesh.getConnectivity(type, ghost_type); const Matrix<UInt> facet_local_connectivity = mesh.getFacetLocalConnectivity(type, ft); UInt nb_nodes_per_facet = connectivity_facets->getNbComponent(); Vector<UInt> facet(nb_nodes_per_facet); for (UInt el = 0; el < nb_element; ++el) { current_element.element = el; for (UInt f = 0; f < nb_facet_per_element; ++f) { for (UInt n = 0; n < nb_nodes_per_facet; ++n) facet(n) = element_connectivity(el, facet_local_connectivity(f, n)); UInt first_node_nb_elements = node_to_elem.getNbCols(facet(0)); counter.resize(first_node_nb_elements); counter.clear(); // loop over the other nodes to search intersecting elements, // which are the elements that share another node with the // starting element after first_node CSR<Element>::iterator first_node_elements = node_to_elem.begin(facet(0)); CSR<Element>::iterator first_node_elements_end = node_to_elem.end(facet(0)); UInt local_el = 0; for (; first_node_elements != first_node_elements_end; ++first_node_elements, ++local_el) { for (UInt n = 1; n < nb_nodes_per_facet; ++n) { CSR<Element>::iterator node_elements_begin = node_to_elem.begin(facet(n)); CSR<Element>::iterator node_elements_end = node_to_elem.end(facet(n)); counter(local_el) += std::count(node_elements_begin, node_elements_end, *first_node_elements); } } // counting the number of elements connected to the facets and // taking the minimum element number, because the facet should // be inserted just once UInt nb_element_connected_to_facet = 0; Element minimum_el = ElementNull; connected_elements.clear(); for (UInt el_f = 0; el_f < first_node_nb_elements; el_f++) { Element real_el = node_to_elem(facet(0), el_f); if (counter(el_f) == nb_nodes_per_facet - 1) { ++nb_element_connected_to_facet; minimum_el = std::min(minimum_el, real_el); connected_elements.push_back(real_el); } } if (minimum_el == current_element) { bool full_ghost_facet = false; UInt n = 0; while (n < nb_nodes_per_facet && mesh.isPureGhostNode(facet(n))) ++n; if (n == nb_nodes_per_facet) full_ghost_facet = true; if (!full_ghost_facet) { if (!boundary_only || (boundary_only && nb_element_connected_to_facet == 1)) { std::vector<Element> elements; // build elements_on_facets: linearized_el must come first // in order to store the facet in the correct direction // and avoid to invert the sign in the normal computation elements.push_back(current_element); /// boundary facet if (nb_element_connected_to_facet == 1) elements.push_back(ElementNull); /// internal facet else if (nb_element_connected_to_facet == 2) { elements.push_back(connected_elements[1]); /// check if facet is in between ghost and normal /// elements: if it's the case, the facet is either /// ghost or not ghost. The criterion to decide this /// is arbitrary. It was chosen to check the processor /// id (prank) of the two neighboring elements. If /// prank of the ghost element is lower than prank of /// the normal one, the facet is not ghost, otherwise /// it's ghost GhostType gt[2] = {_not_ghost, _not_ghost}; for (UInt el = 0; el < connected_elements.size(); ++el) gt[el] = connected_elements[el].ghost_type; if (gt[0] + gt[1] == 1) { if (prank_to_element) { UInt prank[2]; for (UInt el = 0; el < 2; ++el) { UInt current_el = connected_elements[el].element; ElementType current_type = connected_elements[el].type; GhostType current_gt = connected_elements[el].ghost_type; const Array<UInt> & prank_to_el = (*prank_to_element)(current_type, current_gt); prank[el] = prank_to_el(current_el); } bool ghost_one = (gt[0] != _ghost); if (prank[ghost_one] > prank[!ghost_one]) facet_ghost_type = _not_ghost; else facet_ghost_type = _ghost; connectivity_facets = &mesh_facets.getConnectivity( facet_type, facet_ghost_type); element_to_subelement = &mesh_facets.getElementToSubelement( facet_type, facet_ghost_type); } } } /// facet of facet else { for (UInt i = 1; i < nb_element_connected_to_facet; ++i) { elements.push_back(connected_elements[i]); } } element_to_subelement->push_back(elements); connectivity_facets->push_back(facet); /// current facet index UInt current_facet = connectivity_facets->getSize() - 1; /// loop on every element connected to current facet and /// insert current facet in the first free spot of the /// subelement_to_element vector for (UInt elem = 0; elem < elements.size(); ++elem) { Element loc_el = elements[elem]; if (loc_el.type != _not_defined) { Array<Element> & subelement_to_element = mesh_facets.getSubelementToElement(loc_el.type, loc_el.ghost_type); UInt nb_facet_per_loc_element = subelement_to_element.getNbComponent(); for (UInt f_in = 0; f_in < nb_facet_per_loc_element; ++f_in) { if (subelement_to_element(loc_el.element, f_in).type == _not_defined) { subelement_to_element(loc_el.element, f_in).type = facet_type; subelement_to_element(loc_el.element, f_in).element = current_facet; subelement_to_element(loc_el.element, f_in) .ghost_type = facet_ghost_type; break; } } } } /// reset connectivity in case a facet was found in /// between ghost and normal elements if (facet_ghost_type != ghost_type) { facet_ghost_type = ghost_type; connectivity_facets = &mesh_accessor.getConnectivity( facet_type, facet_ghost_type); element_to_subelement = &mesh_accessor.getElementToSubelement(facet_type, facet_ghost_type); } } } } } } } } } // restore the parent of mesh_facet if (mesh_facets_parent) mesh_facets.defineMeshParent(*mesh_facets_parent); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::renumberMeshNodes(Mesh & mesh, Array<UInt> & local_connectivities, UInt nb_local_element, UInt nb_ghost_element, ElementType type, Array<UInt> & old_nodes_numbers) { AKANTU_DEBUG_IN(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); std::map<UInt, UInt> renumbering_map; for (UInt i = 0; i < old_nodes_numbers.getSize(); ++i) { renumbering_map[old_nodes_numbers(i)] = i; } /// renumber the nodes renumberNodesInConnectivity(local_connectivities, (nb_local_element + nb_ghost_element) * nb_nodes_per_element, renumbering_map); std::map<UInt, UInt>::iterator it = renumbering_map.begin(); std::map<UInt, UInt>::iterator end = renumbering_map.end(); old_nodes_numbers.resize(renumbering_map.size()); for (; it != end; ++it) { old_nodes_numbers(it->second) = it->first; } renumbering_map.clear(); MeshAccessor mesh_accessor(mesh); /// copy the renumbered connectivity to the right place Array<UInt> & local_conn = mesh_accessor.getConnectivity(type); local_conn.resize(nb_local_element); memcpy(local_conn.storage(), local_connectivities.storage(), nb_local_element * nb_nodes_per_element * sizeof(UInt)); Array<UInt> & ghost_conn = mesh_accessor.getConnectivity(type, _ghost); ghost_conn.resize(nb_ghost_element); memcpy(ghost_conn.storage(), local_connectivities.storage() + nb_local_element * nb_nodes_per_element, nb_ghost_element * nb_nodes_per_element * sizeof(UInt)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::renumberNodesInConnectivity( Array<UInt> & list_nodes, UInt nb_nodes, std::map<UInt, UInt> & renumbering_map) { AKANTU_DEBUG_IN(); UInt * connectivity = list_nodes.storage(); UInt new_node_num = renumbering_map.size(); for (UInt n = 0; n < nb_nodes; ++n, ++connectivity) { UInt & node = *connectivity; std::map<UInt, UInt>::iterator it = renumbering_map.find(node); if (it == renumbering_map.end()) { UInt old_node = node; renumbering_map[old_node] = new_node_num; node = new_node_num; ++new_node_num; } else { node = it->second; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::purifyMesh(Mesh & mesh) { AKANTU_DEBUG_IN(); std::map<UInt, UInt> renumbering_map; RemovedNodesEvent remove_nodes(mesh); Array<UInt> & nodes_removed = remove_nodes.getList(); for (UInt gt = _not_ghost; gt <= _ghost; ++gt) { GhostType ghost_type = (GhostType)gt; Mesh::type_iterator it = mesh.firstType(_all_dimensions, ghost_type, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(_all_dimensions, ghost_type, _ek_not_defined); for (; it != end; ++it) { ElementType type(*it); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); Array<UInt> & connectivity = mesh.getConnectivity(type, ghost_type); UInt nb_element(connectivity.getSize()); renumberNodesInConnectivity( connectivity, nb_element * nb_nodes_per_element, renumbering_map); } } Array<UInt> & new_numbering = remove_nodes.getNewNumbering(); std::fill(new_numbering.begin(), new_numbering.end(), UInt(-1)); std::map<UInt, UInt>::iterator it = renumbering_map.begin(); std::map<UInt, UInt>::iterator end = renumbering_map.end(); for (; it != end; ++it) { new_numbering(it->first) = it->second; } for (UInt i = 0; i < new_numbering.getSize(); ++i) { if (new_numbering(i) == UInt(-1)) nodes_removed.push_back(i); } mesh.sendEvent(remove_nodes); AKANTU_DEBUG_OUT(); } #if defined(AKANTU_COHESIVE_ELEMENT) /* -------------------------------------------------------------------------- */ UInt MeshUtils::insertCohesiveElements( Mesh & mesh, Mesh & mesh_facets, const ElementTypeMapArray<bool> & facet_insertion, Array<UInt> & doubled_nodes, Array<Element> & new_elements, bool only_double_facets) { UInt spatial_dimension = mesh.getSpatialDimension(); UInt elements_to_insert = updateFacetToDouble(mesh_facets, facet_insertion); if (elements_to_insert > 0) { if (spatial_dimension == 1) { doublePointFacet(mesh, mesh_facets, doubled_nodes); } else { doubleFacet(mesh, mesh_facets, spatial_dimension - 1, doubled_nodes, true); findSubfacetToDouble<false>(mesh, mesh_facets); if (spatial_dimension == 2) { doubleSubfacet<2>(mesh, mesh_facets, doubled_nodes); } else if (spatial_dimension == 3) { doubleFacet(mesh, mesh_facets, 1, doubled_nodes, false); findSubfacetToDouble<true>(mesh, mesh_facets); doubleSubfacet<3>(mesh, mesh_facets, doubled_nodes); } } if (!only_double_facets) updateCohesiveData(mesh, mesh_facets, new_elements); } return elements_to_insert; } #endif /* -------------------------------------------------------------------------- */ void MeshUtils::doubleNodes(Mesh & mesh, const std::vector<UInt> & old_nodes, Array<UInt> & doubled_nodes) { AKANTU_DEBUG_IN(); Array<Real> & position = mesh.getNodes(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt old_nb_nodes = position.getSize(); UInt new_nb_nodes = old_nb_nodes + old_nodes.size(); UInt old_nb_doubled_nodes = doubled_nodes.getSize(); UInt new_nb_doubled_nodes = old_nb_doubled_nodes + old_nodes.size(); position.resize(new_nb_nodes); doubled_nodes.resize(new_nb_doubled_nodes); Array<Real>::iterator<Vector<Real>> position_begin = position.begin(spatial_dimension); for (UInt n = 0; n < old_nodes.size(); ++n) { UInt new_node = old_nb_nodes + n; /// store doubled nodes doubled_nodes(old_nb_doubled_nodes + n, 0) = old_nodes[n]; doubled_nodes(old_nb_doubled_nodes + n, 1) = new_node; /// update position std::copy(position_begin + old_nodes[n], position_begin + old_nodes[n] + 1, position_begin + new_node); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::doubleFacet(Mesh & mesh, Mesh & mesh_facets, UInt facet_dimension, Array<UInt> & doubled_nodes, bool facet_mode) { AKANTU_DEBUG_IN(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh_facets.firstType(facet_dimension, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(facet_dimension, gt_facet); for (; it != end; ++it) { ElementType type_facet = *it; Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet); UInt nb_facet_to_double = f_to_double.getSize(); if (nb_facet_to_double == 0) continue; ElementType type_subfacet = Mesh::getFacetType(type_facet); const UInt nb_subfacet_per_facet = Mesh::getNbFacetsPerElement(type_facet); GhostType gt_subfacet = _casper; Array<std::vector<Element>> * f_to_subfacet = NULL; Array<Element> & subfacet_to_facet = mesh_facets.getSubelementToElement(type_facet, gt_facet); Array<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet); UInt nb_nodes_per_facet = conn_facet.getNbComponent(); UInt old_nb_facet = conn_facet.getSize(); UInt new_nb_facet = old_nb_facet + nb_facet_to_double; conn_facet.resize(new_nb_facet); subfacet_to_facet.resize(new_nb_facet); UInt new_facet = old_nb_facet - 1; Element new_facet_el(type_facet, 0, gt_facet); Array<Element>::iterator<Vector<Element>> subfacet_to_facet_begin = subfacet_to_facet.begin(nb_subfacet_per_facet); Array<UInt>::iterator<Vector<UInt>> conn_facet_begin = conn_facet.begin(nb_nodes_per_facet); for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { UInt old_facet = f_to_double(facet); ++new_facet; /// adding a new facet by copying original one /// copy connectivity in new facet std::copy(conn_facet_begin + old_facet, conn_facet_begin + old_facet + 1, conn_facet_begin + new_facet); /// update subfacet_to_facet std::copy(subfacet_to_facet_begin + old_facet, subfacet_to_facet_begin + old_facet + 1, subfacet_to_facet_begin + new_facet); new_facet_el.element = new_facet; /// loop on every subfacet for (UInt sf = 0; sf < nb_subfacet_per_facet; ++sf) { Element & subfacet = subfacet_to_facet(old_facet, sf); if (subfacet == ElementNull) continue; if (gt_subfacet != subfacet.ghost_type) { gt_subfacet = subfacet.ghost_type; f_to_subfacet = &mesh_facets.getElementToSubelement( type_subfacet, subfacet.ghost_type); } /// update facet_to_subfacet array (*f_to_subfacet)(subfacet.element).push_back(new_facet_el); } } /// update facet_to_subfacet and _segment_3 facets if any if (!facet_mode) { updateSubfacetToFacet(mesh_facets, type_facet, gt_facet, true); updateFacetToSubfacet(mesh_facets, type_facet, gt_facet, true); updateQuadraticSegments<true>(mesh, mesh_facets, type_facet, gt_facet, doubled_nodes); } else updateQuadraticSegments<false>(mesh, mesh_facets, type_facet, gt_facet, doubled_nodes); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ UInt MeshUtils::updateFacetToDouble( Mesh & mesh_facets, const ElementTypeMapArray<bool> & facet_insertion) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh_facets.getSpatialDimension(); UInt nb_facets_to_double = 0.; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet); for (; it != end; ++it) { ElementType type_facet = *it; const Array<bool> & f_insertion = facet_insertion(type_facet, gt_facet); Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet); Array<std::vector<Element>> & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); ElementType el_type = _not_defined; GhostType el_gt = _casper; UInt nb_facet_per_element = 0; Element old_facet_el(type_facet, 0, gt_facet); Array<Element> * facet_to_element = NULL; for (UInt f = 0; f < f_insertion.getSize(); ++f) { if (f_insertion(f) == false) continue; ++nb_facets_to_double; if (element_to_facet(f)[1].type == _not_defined #if defined(AKANTU_COHESIVE_ELEMENT) || element_to_facet(f)[1].kind == _ek_cohesive #endif ) { AKANTU_DEBUG_WARNING("attempt to double a facet on the boundary"); continue; } f_to_double.push_back(f); UInt new_facet = mesh_facets.getNbElement(type_facet, gt_facet) + f_to_double.getSize() - 1; old_facet_el.element = f; /// update facet_to_element vector Element & elem_to_update = element_to_facet(f)[1]; UInt el = elem_to_update.element; if (elem_to_update.ghost_type != el_gt || elem_to_update.type != el_type) { el_type = elem_to_update.type; el_gt = elem_to_update.ghost_type; facet_to_element = &mesh_facets.getSubelementToElement(el_type, el_gt); nb_facet_per_element = facet_to_element->getNbComponent(); } Element * f_update = std::find(facet_to_element->storage() + el * nb_facet_per_element, facet_to_element->storage() + el * nb_facet_per_element + nb_facet_per_element, old_facet_el); AKANTU_DEBUG_ASSERT( facet_to_element->storage() + el * nb_facet_per_element != facet_to_element->storage() + el * nb_facet_per_element + nb_facet_per_element, "Facet not found"); f_update->element = new_facet; /// update elements connected to facet std::vector<Element> first_facet_list = element_to_facet(f); element_to_facet.push_back(first_facet_list); /// set new and original facets as boundary facets element_to_facet(new_facet)[0] = element_to_facet(new_facet)[1]; element_to_facet(f)[1] = ElementNull; element_to_facet(new_facet)[1] = ElementNull; } } } AKANTU_DEBUG_OUT(); return nb_facets_to_double; } /* -------------------------------------------------------------------------- */ void MeshUtils::resetFacetToDouble(Mesh & mesh_facets) { AKANTU_DEBUG_IN(); for (UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType)g; Mesh::type_iterator it = mesh_facets.firstType(_all_dimensions, gt); Mesh::type_iterator end = mesh_facets.lastType(_all_dimensions, gt); for (; it != end; ++it) { ElementType type = *it; mesh_facets.getDataPointer<UInt>("facet_to_double", type, gt, 1, false); mesh_facets.getDataPointer<std::vector<Element>>( "facets_to_subfacet_double", type, gt, 1, false); mesh_facets.getDataPointer<std::vector<Element>>( "elements_to_subfacet_double", type, gt, 1, false); mesh_facets.getDataPointer<std::vector<Element>>( "subfacets_to_subsubfacet_double", type, gt, 1, false); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <bool subsubfacet_mode> void MeshUtils::findSubfacetToDouble(Mesh & mesh, Mesh & mesh_facets) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh_facets.getSpatialDimension(); if (spatial_dimension == 1) return; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet); for (; it != end; ++it) { ElementType type_facet = *it; Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet); UInt nb_facet_to_double = f_to_double.getSize(); if (nb_facet_to_double == 0) continue; ElementType type_subfacet = Mesh::getFacetType(type_facet); GhostType gt_subfacet = _casper; ElementType type_subsubfacet = Mesh::getFacetType(type_subfacet); GhostType gt_subsubfacet = _casper; Array<UInt> * conn_subfacet = NULL; Array<UInt> * sf_to_double = NULL; Array<std::vector<Element>> * sf_to_subfacet_double = NULL; Array<std::vector<Element>> * f_to_subfacet_double = NULL; Array<std::vector<Element>> * el_to_subfacet_double = NULL; UInt nb_subfacet = Mesh::getNbFacetsPerElement(type_facet); UInt nb_subsubfacet; UInt nb_nodes_per_sf_el; if (subsubfacet_mode) { nb_nodes_per_sf_el = Mesh::getNbNodesPerElement(type_subsubfacet); nb_subsubfacet = Mesh::getNbFacetsPerElement(type_subfacet); } else nb_nodes_per_sf_el = Mesh::getNbNodesPerElement(type_subfacet); Array<Element> & subfacet_to_facet = mesh_facets.getSubelementToElement(type_facet, gt_facet); Array<std::vector<Element>> & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); Array<Element> * subsubfacet_to_subfacet = NULL; UInt old_nb_facet = subfacet_to_facet.getSize() - nb_facet_to_double; Element current_facet(type_facet, 0, gt_facet); std::vector<Element> element_list; std::vector<Element> facet_list; std::vector<Element> * subfacet_list; if (subsubfacet_mode) subfacet_list = new std::vector<Element>; /// map to filter subfacets Array<std::vector<Element>> * facet_to_subfacet = NULL; /// this is used to make sure that both new and old facets are /// checked UInt facets[2]; /// loop on every facet for (UInt f_index = 0; f_index < 2; ++f_index) { for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { facets[bool(f_index)] = f_to_double(facet); facets[!bool(f_index)] = old_nb_facet + facet; UInt old_facet = facets[0]; UInt new_facet = facets[1]; Element & starting_element = element_to_facet(new_facet)[0]; current_facet.element = old_facet; /// loop on every subfacet for (UInt sf = 0; sf < nb_subfacet; ++sf) { Element & subfacet = subfacet_to_facet(old_facet, sf); if (subfacet == ElementNull) continue; if (gt_subfacet != subfacet.ghost_type) { gt_subfacet = subfacet.ghost_type; if (subsubfacet_mode) { subsubfacet_to_subfacet = &mesh_facets.getSubelementToElement( type_subfacet, gt_subfacet); } else { conn_subfacet = &mesh_facets.getConnectivity(type_subfacet, gt_subfacet); sf_to_double = &mesh_facets.getData<UInt>( "facet_to_double", type_subfacet, gt_subfacet); f_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "facets_to_subfacet_double", type_subfacet, gt_subfacet); el_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "elements_to_subfacet_double", type_subfacet, gt_subfacet); facet_to_subfacet = &mesh_facets.getElementToSubelement( type_subfacet, gt_subfacet); } } if (subsubfacet_mode) { /// loop on every subsubfacet for (UInt ssf = 0; ssf < nb_subsubfacet; ++ssf) { Element & subsubfacet = (*subsubfacet_to_subfacet)(subfacet.element, ssf); if (subsubfacet == ElementNull) continue; if (gt_subsubfacet != subsubfacet.ghost_type) { gt_subsubfacet = subsubfacet.ghost_type; conn_subfacet = &mesh_facets.getConnectivity(type_subsubfacet, gt_subsubfacet); sf_to_double = &mesh_facets.getData<UInt>( "facet_to_double", type_subsubfacet, gt_subsubfacet); sf_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "subfacets_to_subsubfacet_double", type_subsubfacet, gt_subsubfacet); f_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "facets_to_subfacet_double", type_subsubfacet, gt_subsubfacet); el_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "elements_to_subfacet_double", type_subsubfacet, gt_subsubfacet); facet_to_subfacet = &mesh_facets.getElementToSubelement( type_subsubfacet, gt_subsubfacet); } UInt global_ssf = subsubfacet.element; Vector<UInt> subsubfacet_connectivity( conn_subfacet->storage() + global_ssf * nb_nodes_per_sf_el, nb_nodes_per_sf_el); /// check if subsubfacet is to be doubled if (findElementsAroundSubfacet<true>( mesh, mesh_facets, starting_element, current_facet, subsubfacet_connectivity, element_list, facet_list, subfacet_list) == false && removeElementsInVector(*subfacet_list, (*facet_to_subfacet)(global_ssf)) == false) { sf_to_double->push_back(global_ssf); sf_to_subfacet_double->push_back(*subfacet_list); f_to_subfacet_double->push_back(facet_list); el_to_subfacet_double->push_back(element_list); } } } else { const UInt global_sf = subfacet.element; Vector<UInt> subfacet_connectivity( conn_subfacet->storage() + global_sf * nb_nodes_per_sf_el, nb_nodes_per_sf_el); /// check if subfacet is to be doubled if (findElementsAroundSubfacet<false>( mesh, mesh_facets, starting_element, current_facet, subfacet_connectivity, element_list, facet_list) == false && removeElementsInVector( facet_list, (*facet_to_subfacet)(global_sf)) == false) { sf_to_double->push_back(global_sf); f_to_subfacet_double->push_back(facet_list); el_to_subfacet_double->push_back(element_list); } } } } } if (subsubfacet_mode) delete subfacet_list; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ #if defined(AKANTU_COHESIVE_ELEMENT) void MeshUtils::updateCohesiveData(Mesh & mesh, Mesh & mesh_facets, Array<Element> & new_elements) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); bool third_dimension = spatial_dimension == 3; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet); for (; it != end; ++it) { ElementType type_facet = *it; Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet); UInt nb_facet_to_double = f_to_double.getSize(); if (nb_facet_to_double == 0) continue; ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet); Array<Element> * facet_to_coh_element = mesh_facets.getSubelementToElementPointer(type_cohesive, gt_facet); Array<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet); Array<UInt> * conn_cohesive = mesh.getConnectivityPointer(type_cohesive, gt_facet); UInt nb_nodes_per_facet = Mesh::getNbNodesPerElement(type_facet); Array<std::vector<Element>> & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); UInt old_nb_cohesive_elements = conn_cohesive->getSize(); UInt new_nb_cohesive_elements = conn_cohesive->getSize() + nb_facet_to_double; UInt old_nb_facet = element_to_facet.getSize() - nb_facet_to_double; facet_to_coh_element->resize(new_nb_cohesive_elements); conn_cohesive->resize(new_nb_cohesive_elements); UInt new_elements_old_size = new_elements.getSize(); new_elements.resize(new_elements_old_size + nb_facet_to_double); Element c_element(type_cohesive, 0, gt_facet, _ek_cohesive); Element f_element(type_facet, 0, gt_facet); UInt facets[2]; for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { /// (in 3D cohesive elements connectivity is inverted) facets[third_dimension] = f_to_double(facet); facets[!third_dimension] = old_nb_facet + facet; UInt cohesive_element = old_nb_cohesive_elements + facet; /// store doubled facets f_element.element = facets[0]; (*facet_to_coh_element)(cohesive_element, 0) = f_element; f_element.element = facets[1]; (*facet_to_coh_element)(cohesive_element, 1) = f_element; /// modify cohesive elements' connectivity for (UInt n = 0; n < nb_nodes_per_facet; ++n) { (*conn_cohesive)(cohesive_element, n) = conn_facet(facets[0], n); (*conn_cohesive)(cohesive_element, n + nb_nodes_per_facet) = conn_facet(facets[1], n); } /// update element_to_facet vectors c_element.element = cohesive_element; element_to_facet(facets[0])[1] = c_element; element_to_facet(facets[1])[1] = c_element; /// add cohesive element to the element event list new_elements(new_elements_old_size + facet) = c_element; } } } AKANTU_DEBUG_OUT(); } #endif /* -------------------------------------------------------------------------- */ void MeshUtils::doublePointFacet(Mesh & mesh, Mesh & mesh_facets, Array<UInt> & doubled_nodes) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); if (spatial_dimension != 1) return; Array<Real> & position = mesh.getNodes(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet); for (; it != end; ++it) { ElementType type_facet = *it; Array<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet); Array<std::vector<Element>> & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); const Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet); UInt nb_facet_to_double = f_to_double.getSize(); UInt old_nb_facet = element_to_facet.getSize() - nb_facet_to_double; UInt new_nb_facet = element_to_facet.getSize(); UInt old_nb_nodes = position.getSize(); UInt new_nb_nodes = old_nb_nodes + nb_facet_to_double; position.resize(new_nb_nodes); conn_facet.resize(new_nb_facet); UInt old_nb_doubled_nodes = doubled_nodes.getSize(); doubled_nodes.resize(old_nb_doubled_nodes + nb_facet_to_double); for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { UInt old_facet = f_to_double(facet); UInt new_facet = old_nb_facet + facet; ElementType type = element_to_facet(new_facet)[0].type; UInt el = element_to_facet(new_facet)[0].element; GhostType gt = element_to_facet(new_facet)[0].ghost_type; UInt old_node = conn_facet(old_facet); UInt new_node = old_nb_nodes + facet; /// update position position(new_node) = position(old_node); conn_facet(new_facet) = new_node; Array<UInt> & conn_segment = mesh.getConnectivity(type, gt); UInt nb_nodes_per_segment = conn_segment.getNbComponent(); /// update facet connectivity UInt i; for (i = 0; conn_segment(el, i) != old_node && i <= nb_nodes_per_segment; ++i) ; conn_segment(el, i) = new_node; doubled_nodes(old_nb_doubled_nodes + facet, 0) = old_node; doubled_nodes(old_nb_doubled_nodes + facet, 1) = new_node; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <bool third_dim_segments> void MeshUtils::updateQuadraticSegments(Mesh & mesh, Mesh & mesh_facets, ElementType type_facet, GhostType gt_facet, Array<UInt> & doubled_nodes) { AKANTU_DEBUG_IN(); if (type_facet != _segment_3) return; Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet); UInt nb_facet_to_double = f_to_double.getSize(); UInt old_nb_facet = mesh_facets.getNbElement(type_facet, gt_facet) - nb_facet_to_double; Array<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet); Array<std::vector<Element>> & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); /// this ones matter only for segments in 3D Array<std::vector<Element>> * el_to_subfacet_double = NULL; Array<std::vector<Element>> * f_to_subfacet_double = NULL; if (third_dim_segments) { el_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "elements_to_subfacet_double", type_facet, gt_facet); f_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "facets_to_subfacet_double", type_facet, gt_facet); } std::vector<UInt> middle_nodes; for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { UInt old_facet = f_to_double(facet); UInt node = conn_facet(old_facet, 2); if (!mesh.isPureGhostNode(node)) middle_nodes.push_back(node); } UInt n = doubled_nodes.getSize(); doubleNodes(mesh, middle_nodes, doubled_nodes); for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { UInt old_facet = f_to_double(facet); UInt old_node = conn_facet(old_facet, 2); if (mesh.isPureGhostNode(old_node)) continue; UInt new_node = doubled_nodes(n, 1); UInt new_facet = old_nb_facet + facet; conn_facet(new_facet, 2) = new_node; if (third_dim_segments) { updateElementalConnectivity(mesh_facets, old_node, new_node, element_to_facet(new_facet)); updateElementalConnectivity(mesh, old_node, new_node, (*el_to_subfacet_double)(facet), &(*f_to_subfacet_double)(facet)); } else { updateElementalConnectivity(mesh, old_node, new_node, element_to_facet(new_facet)); } ++n; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::updateSubfacetToFacet(Mesh & mesh_facets, ElementType type_subfacet, GhostType gt_subfacet, bool facet_mode) { AKANTU_DEBUG_IN(); Array<UInt> & sf_to_double = mesh_facets.getData<UInt>("facet_to_double", type_subfacet, gt_subfacet); UInt nb_subfacet_to_double = sf_to_double.getSize(); /// update subfacet_to_facet vector ElementType type_facet = _not_defined; GhostType gt_facet = _casper; Array<Element> * subfacet_to_facet = NULL; UInt nb_subfacet_per_facet = 0; UInt old_nb_subfacet = mesh_facets.getNbElement(type_subfacet, gt_subfacet) - nb_subfacet_to_double; Array<std::vector<Element>> * facet_list = NULL; if (facet_mode) facet_list = &mesh_facets.getData<std::vector<Element>>( "facets_to_subfacet_double", type_subfacet, gt_subfacet); else facet_list = &mesh_facets.getData<std::vector<Element>>( "subfacets_to_subsubfacet_double", type_subfacet, gt_subfacet); Element old_subfacet_el(type_subfacet, 0, gt_subfacet); Element new_subfacet_el(type_subfacet, 0, gt_subfacet); for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) { old_subfacet_el.element = sf_to_double(sf); new_subfacet_el.element = old_nb_subfacet + sf; for (UInt f = 0; f < (*facet_list)(sf).size(); ++f) { Element & facet = (*facet_list)(sf)[f]; if (facet.type != type_facet || facet.ghost_type != gt_facet) { type_facet = facet.type; gt_facet = facet.ghost_type; subfacet_to_facet = &mesh_facets.getSubelementToElement(type_facet, gt_facet); nb_subfacet_per_facet = subfacet_to_facet->getNbComponent(); } Element * sf_update = std::find( subfacet_to_facet->storage() + facet.element * nb_subfacet_per_facet, subfacet_to_facet->storage() + facet.element * nb_subfacet_per_facet + nb_subfacet_per_facet, old_subfacet_el); AKANTU_DEBUG_ASSERT(subfacet_to_facet->storage() + facet.element * nb_subfacet_per_facet != subfacet_to_facet->storage() + facet.element * nb_subfacet_per_facet + nb_subfacet_per_facet, "Subfacet not found"); *sf_update = new_subfacet_el; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::updateFacetToSubfacet(Mesh & mesh_facets, ElementType type_subfacet, GhostType gt_subfacet, bool facet_mode) { AKANTU_DEBUG_IN(); Array<UInt> & sf_to_double = mesh_facets.getData<UInt>("facet_to_double", type_subfacet, gt_subfacet); UInt nb_subfacet_to_double = sf_to_double.getSize(); Array<std::vector<Element>> & facet_to_subfacet = mesh_facets.getElementToSubelement(type_subfacet, gt_subfacet); Array<std::vector<Element>> * facet_to_subfacet_double = NULL; if (facet_mode) { facet_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "facets_to_subfacet_double", type_subfacet, gt_subfacet); } else { facet_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "subfacets_to_subsubfacet_double", type_subfacet, gt_subfacet); } UInt old_nb_subfacet = facet_to_subfacet.getSize(); facet_to_subfacet.resize(old_nb_subfacet + nb_subfacet_to_double); for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) facet_to_subfacet(old_nb_subfacet + sf) = (*facet_to_subfacet_double)(sf); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MeshUtils::doubleSubfacet(Mesh & mesh, Mesh & mesh_facets, Array<UInt> & doubled_nodes) { AKANTU_DEBUG_IN(); if (spatial_dimension == 1) return; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_subfacet = *gt; Mesh::type_iterator it = mesh_facets.firstType(0, gt_subfacet); Mesh::type_iterator end = mesh_facets.lastType(0, gt_subfacet); for (; it != end; ++it) { ElementType type_subfacet = *it; Array<UInt> & sf_to_double = mesh_facets.getData<UInt>( "facet_to_double", type_subfacet, gt_subfacet); UInt nb_subfacet_to_double = sf_to_double.getSize(); if (nb_subfacet_to_double == 0) continue; AKANTU_DEBUG_ASSERT( type_subfacet == _point_1, "Only _point_1 subfacet doubling is supported at the moment"); Array<UInt> & conn_subfacet = mesh_facets.getConnectivity(type_subfacet, gt_subfacet); UInt old_nb_subfacet = conn_subfacet.getSize(); UInt new_nb_subfacet = old_nb_subfacet + nb_subfacet_to_double; conn_subfacet.resize(new_nb_subfacet); std::vector<UInt> nodes_to_double; UInt old_nb_doubled_nodes = doubled_nodes.getSize(); /// double nodes for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) { UInt old_subfacet = sf_to_double(sf); nodes_to_double.push_back(conn_subfacet(old_subfacet)); } doubleNodes(mesh, nodes_to_double, doubled_nodes); /// add new nodes in connectivity for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) { UInt new_subfacet = old_nb_subfacet + sf; UInt new_node = doubled_nodes(old_nb_doubled_nodes + sf, 1); conn_subfacet(new_subfacet) = new_node; } /// update facet and element connectivity Array<std::vector<Element>> & f_to_subfacet_double = mesh_facets.getData<std::vector<Element>>("facets_to_subfacet_double", type_subfacet, gt_subfacet); Array<std::vector<Element>> & el_to_subfacet_double = mesh_facets.getData<std::vector<Element>>( "elements_to_subfacet_double", type_subfacet, gt_subfacet); Array<std::vector<Element>> * sf_to_subfacet_double = NULL; if (spatial_dimension == 3) sf_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "subfacets_to_subsubfacet_double", type_subfacet, gt_subfacet); for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) { UInt old_node = doubled_nodes(old_nb_doubled_nodes + sf, 0); UInt new_node = doubled_nodes(old_nb_doubled_nodes + sf, 1); updateElementalConnectivity(mesh, old_node, new_node, el_to_subfacet_double(sf), &f_to_subfacet_double(sf)); updateElementalConnectivity(mesh_facets, old_node, new_node, f_to_subfacet_double(sf)); if (spatial_dimension == 3) updateElementalConnectivity(mesh_facets, old_node, new_node, (*sf_to_subfacet_double)(sf)); } if (spatial_dimension == 2) { updateSubfacetToFacet(mesh_facets, type_subfacet, gt_subfacet, true); updateFacetToSubfacet(mesh_facets, type_subfacet, gt_subfacet, true); } else if (spatial_dimension == 3) { updateSubfacetToFacet(mesh_facets, type_subfacet, gt_subfacet, false); updateFacetToSubfacet(mesh_facets, type_subfacet, gt_subfacet, false); } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::flipFacets( Mesh & mesh_facets, const ElementTypeMapArray<UInt> & global_connectivity, GhostType gt_facet) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh_facets.getSpatialDimension(); /// get global connectivity for local mesh ElementTypeMapArray<UInt> global_connectivity_tmp("global_connectivity_tmp", mesh_facets.getID(), mesh_facets.getMemoryID()); mesh_facets.initElementTypeMapArray(global_connectivity_tmp, 1, spatial_dimension - 1, gt_facet, true, _ek_regular, true); mesh_facets.getGlobalConnectivity(global_connectivity_tmp, spatial_dimension - 1, gt_facet); Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet); /// loop on every facet for (; it != end; ++it) { ElementType type_facet = *it; Array<UInt> & connectivity = mesh_facets.getConnectivity(type_facet, gt_facet); const Array<UInt> & g_connectivity = global_connectivity(type_facet, gt_facet); Array<std::vector<Element>> & el_to_f = mesh_facets.getElementToSubelement(type_facet, gt_facet); Array<Element> & subfacet_to_facet = mesh_facets.getSubelementToElement(type_facet, gt_facet); UInt nb_subfacet_per_facet = subfacet_to_facet.getNbComponent(); UInt nb_nodes_per_facet = connectivity.getNbComponent(); UInt nb_facet = connectivity.getSize(); UInt nb_nodes_per_P1_facet = Mesh::getNbNodesPerElement(Mesh::getP1ElementType(type_facet)); Array<UInt> & global_conn_tmp = global_connectivity_tmp(type_facet, gt_facet); Array<UInt>::iterator<Vector<UInt>> conn_it = connectivity.begin(nb_nodes_per_facet); Array<UInt>::iterator<Vector<UInt>> gconn_tmp_it = global_conn_tmp.begin(nb_nodes_per_facet); Array<UInt>::const_iterator<Vector<UInt>> conn_glob_it = g_connectivity.begin(nb_nodes_per_facet); Array<Element>::iterator<Vector<Element>> subf_to_f = subfacet_to_facet.begin(nb_subfacet_per_facet); UInt * conn_tmp_pointer = new UInt[nb_nodes_per_facet]; Vector<UInt> conn_tmp(conn_tmp_pointer, nb_nodes_per_facet); Element el_tmp; Element * subf_tmp_pointer = new Element[nb_subfacet_per_facet]; Vector<Element> subf_tmp(subf_tmp_pointer, nb_subfacet_per_facet); for (UInt f = 0; f < nb_facet; ++f, ++conn_it, ++gconn_tmp_it, ++subf_to_f, ++conn_glob_it) { Vector<UInt> & gconn_tmp = *gconn_tmp_it; const Vector<UInt> & conn_glob = *conn_glob_it; Vector<UInt> & conn_local = *conn_it; /// skip facet if connectivities are the same if (gconn_tmp == conn_glob) continue; /// re-arrange connectivity conn_tmp = conn_local; UInt * begin = conn_glob.storage(); UInt * end = conn_glob.storage() + nb_nodes_per_facet; for (UInt n = 0; n < nb_nodes_per_facet; ++n) { UInt * new_node = std::find(begin, end, gconn_tmp(n)); AKANTU_DEBUG_ASSERT(new_node != end, "Node not found"); UInt new_position = new_node - begin; conn_local(new_position) = conn_tmp(n); } /// if 3D, check if facets are just rotated if (spatial_dimension == 3) { /// find first node UInt * new_node = std::find(begin, end, gconn_tmp(0)); AKANTU_DEBUG_ASSERT(new_node != end, "Node not found"); UInt new_position = new_node - begin; UInt n = 1; /// count how many nodes in the received connectivity follow /// the same order of those in the local connectivity for (; n < nb_nodes_per_P1_facet && gconn_tmp(n) == conn_glob((new_position + n) % nb_nodes_per_P1_facet); ++n) ; /// skip the facet inversion if facet is just rotated if (n == nb_nodes_per_P1_facet) continue; } /// update data to invert facet el_tmp = el_to_f(f)[0]; el_to_f(f)[0] = el_to_f(f)[1]; el_to_f(f)[1] = el_tmp; subf_tmp = (*subf_to_f); (*subf_to_f)(0) = subf_tmp(1); (*subf_to_f)(1) = subf_tmp(0); } delete[] subf_tmp_pointer; delete[] conn_tmp_pointer; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::fillElementToSubElementsData(Mesh & mesh) { AKANTU_DEBUG_IN(); if (mesh.getNbElement(mesh.getSpatialDimension() - 1) == 0) { AKANTU_DEBUG_INFO("There are not facets, add them in the mesh file or call " "the buildFacet method."); return; } UInt spatial_dimension = mesh.getSpatialDimension(); ElementTypeMapArray<Real> barycenters("barycenter_tmp", mesh.getID(), mesh.getMemoryID()); mesh.initElementTypeMapArray(barycenters, spatial_dimension, _all_dimensions); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { Mesh::type_iterator it = mesh.firstType(_all_dimensions, *gt); Mesh::type_iterator end = mesh.lastType(_all_dimensions, *gt); for (; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it, *gt); Array<Real> & barycenters_arr = barycenters(*it, *gt); barycenters_arr.resize(nb_element); Array<Real>::vector_iterator bary = barycenters_arr.begin(spatial_dimension); Array<Real>::vector_iterator bary_end = barycenters_arr.end(spatial_dimension); for (UInt el = 0; bary != bary_end; ++bary, ++el) { mesh.getBarycenter(el, *it, bary->storage(), *gt); } } } MeshAccessor mesh_accessor(mesh); for (Int sp(spatial_dimension); sp >= 1; --sp) { if (mesh.getNbElement(sp) == 0) continue; for (ghost_type_t::iterator git = ghost_type_t::begin(); git != ghost_type_t::end(); ++git) { Mesh::type_iterator tit = mesh.firstType(sp, *git); Mesh::type_iterator tend = mesh.lastType(sp, *git); for (; tit != tend; ++tit) { mesh_accessor.getSubelementToElement(*tit, *git) .resize(mesh.getNbElement(*tit, *git)); mesh_accessor.getSubelementToElement(*tit, *git).clear(); } tit = mesh.firstType(sp - 1, *git); tend = mesh.lastType(sp - 1, *git); for (; tit != tend; ++tit) { mesh_accessor.getElementToSubelement(*tit, *git) .resize(mesh.getNbElement(*tit, *git)); mesh.getElementToSubelement(*tit, *git).clear(); } } CSR<Element> nodes_to_elements; buildNode2Elements(mesh, nodes_to_elements, sp); Element facet_element; for (ghost_type_t::iterator git = ghost_type_t::begin(); git != ghost_type_t::end(); ++git) { Mesh::type_iterator tit = mesh.firstType(sp - 1, *git); Mesh::type_iterator tend = mesh.lastType(sp - 1, *git); facet_element.ghost_type = *git; for (; tit != tend; ++tit) { facet_element.type = *tit; Array<std::vector<Element>> & element_to_subelement = mesh.getElementToSubelement(*tit, *git); const Array<UInt> & connectivity = mesh.getConnectivity(*tit, *git); Array<UInt>::const_iterator<Vector<UInt>> fit = connectivity.begin(mesh.getNbNodesPerElement(*tit)); Array<UInt>::const_iterator<Vector<UInt>> fend = connectivity.end(mesh.getNbNodesPerElement(*tit)); UInt fid = 0; for (; fit != fend; ++fit, ++fid) { const Vector<UInt> & facet = *fit; facet_element.element = fid; std::map<Element, UInt> element_seen_counter; UInt nb_nodes_per_facet = mesh.getNbNodesPerElement(Mesh::getP1ElementType(*tit)); for (UInt n(0); n < nb_nodes_per_facet; ++n) { CSR<Element>::iterator eit = nodes_to_elements.begin(facet(n)); CSR<Element>::iterator eend = nodes_to_elements.end(facet(n)); for (; eit != eend; ++eit) { Element & elem = *eit; std::map<Element, UInt>::iterator cit = element_seen_counter.find(elem); if (cit != element_seen_counter.end()) { cit->second++; } else { element_seen_counter[elem] = 1; } } } std::vector<Element> connected_elements; std::map<Element, UInt>::iterator cit = element_seen_counter.begin(); std::map<Element, UInt>::iterator cend = element_seen_counter.end(); for (; cit != cend; ++cit) { if (cit->second == nb_nodes_per_facet) connected_elements.push_back(cit->first); } std::vector<Element>::iterator ceit = connected_elements.begin(); std::vector<Element>::iterator ceend = connected_elements.end(); for (; ceit != ceend; ++ceit) element_to_subelement(fid).push_back(*ceit); for (UInt ce = 0; ce < connected_elements.size(); ++ce) { Element & elem = connected_elements[ce]; Array<Element> & subelement_to_element = mesh_accessor.getSubelementToElement(elem.type, elem.ghost_type); UInt f(0); for (; f < mesh.getNbFacetsPerElement(elem.type) && subelement_to_element(elem.element, f) != ElementNull; ++f) ; AKANTU_DEBUG_ASSERT( f < mesh.getNbFacetsPerElement(elem.type), "The element " << elem << " seems to have too many facets!! (" << f << " < " << mesh.getNbFacetsPerElement(elem.type) << ")"); subelement_to_element(elem.element, f) = facet_element; } } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <bool third_dim_points> bool MeshUtils::findElementsAroundSubfacet( const Mesh & mesh, const Mesh & mesh_facets, const Element & starting_element, const Element & end_facet, const Vector<UInt> & subfacet_connectivity, std::vector<Element> & elem_list, std::vector<Element> & facet_list, std::vector<Element> * subfacet_list) { AKANTU_DEBUG_IN(); /// preallocated stuff before starting bool facet_matched = false; elem_list.clear(); facet_list.clear(); if (third_dim_points) subfacet_list->clear(); elem_list.push_back(starting_element); const Array<UInt> * facet_connectivity = NULL; const Array<UInt> * sf_connectivity = NULL; const Array<Element> * facet_to_element = NULL; const Array<Element> * subfacet_to_facet = NULL; ElementType current_type = _not_defined; GhostType current_ghost_type = _casper; ElementType current_facet_type = _not_defined; GhostType current_facet_ghost_type = _casper; ElementType current_subfacet_type = _not_defined; GhostType current_subfacet_ghost_type = _casper; const Array<std::vector<Element>> * element_to_facet = NULL; const Element * opposing_el = NULL; std::queue<Element> elements_to_check; elements_to_check.push(starting_element); /// keep going until there are elements to check while (!elements_to_check.empty()) { /// check current element Element & current_el = elements_to_check.front(); if (current_el.type != current_type || current_el.ghost_type != current_ghost_type) { current_type = current_el.type; current_ghost_type = current_el.ghost_type; facet_to_element = &mesh_facets.getSubelementToElement(current_type, current_ghost_type); } /// loop over each facet of the element for (UInt f = 0; f < facet_to_element->getNbComponent(); ++f) { const Element & current_facet = (*facet_to_element)(current_el.element, f); if (current_facet == ElementNull) continue; if (current_facet_type != current_facet.type || current_facet_ghost_type != current_facet.ghost_type) { current_facet_type = current_facet.type; current_facet_ghost_type = current_facet.ghost_type; element_to_facet = &mesh_facets.getElementToSubelement( current_facet_type, current_facet_ghost_type); facet_connectivity = &mesh_facets.getConnectivity( current_facet_type, current_facet_ghost_type); if (third_dim_points) subfacet_to_facet = &mesh_facets.getSubelementToElement( current_facet_type, current_facet_ghost_type); } /// check if end facet is reached if (current_facet == end_facet) facet_matched = true; /// add this facet if not already passed if (std::find(facet_list.begin(), facet_list.end(), current_facet) == facet_list.end() && hasElement(*facet_connectivity, current_facet, subfacet_connectivity)) { facet_list.push_back(current_facet); if (third_dim_points) { /// check subfacets for (UInt sf = 0; sf < subfacet_to_facet->getNbComponent(); ++sf) { const Element & current_subfacet = (*subfacet_to_facet)(current_facet.element, sf); if (current_subfacet == ElementNull) continue; if (current_subfacet_type != current_subfacet.type || current_subfacet_ghost_type != current_subfacet.ghost_type) { current_subfacet_type = current_subfacet.type; current_subfacet_ghost_type = current_subfacet.ghost_type; sf_connectivity = &mesh_facets.getConnectivity( current_subfacet_type, current_subfacet_ghost_type); } if (std::find(subfacet_list->begin(), subfacet_list->end(), current_subfacet) == subfacet_list->end() && hasElement(*sf_connectivity, current_subfacet, subfacet_connectivity)) subfacet_list->push_back(current_subfacet); } } } else continue; /// consider opposing element if ((*element_to_facet)(current_facet.element)[0] == current_el) opposing_el = &(*element_to_facet)(current_facet.element)[1]; else opposing_el = &(*element_to_facet)(current_facet.element)[0]; /// skip null elements since they are on a boundary if (*opposing_el == ElementNull) continue; /// skip this element if already added if (std::find(elem_list.begin(), elem_list.end(), *opposing_el) != elem_list.end()) continue; /// only regular elements have to be checked if (opposing_el->kind == _ek_regular) elements_to_check.push(*opposing_el); elem_list.push_back(*opposing_el); #ifndef AKANTU_NDEBUG const Array<UInt> & conn_elem = mesh.getConnectivity(opposing_el->type, opposing_el->ghost_type); AKANTU_DEBUG_ASSERT( hasElement(conn_elem, *opposing_el, subfacet_connectivity), "Subfacet doesn't belong to this element"); #endif } /// erased checked element from the list elements_to_check.pop(); } AKANTU_DEBUG_OUT(); return facet_matched; } /* -------------------------------------------------------------------------- */ void MeshUtils::buildSegmentToNodeType(const Mesh & mesh, Mesh & mesh_facets) { buildAllFacets(mesh, mesh_facets, 1); UInt spatial_dimension = mesh.getSpatialDimension(); const ElementTypeMapArray<UInt> & element_to_rank = mesh.getElementSynchronizer().getPrankToElement(); Int local_rank = StaticCommunicator::getStaticCommunicator().whoAmI(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Mesh::type_iterator it = mesh_facets.firstType(1, ghost_type); Mesh::type_iterator end = mesh_facets.lastType(1, ghost_type); for (; it != end; ++it) { ElementType type = *it; UInt nb_segments = mesh_facets.getNbElement(type, ghost_type); // allocate the data Array<Int> & segment_to_nodetype = *(mesh_facets.getDataPointer<Int>( "segment_to_nodetype", type, ghost_type)); std::set<Element> connected_elements; const Array<std::vector<Element>> & segment_to_2Delement = mesh_facets.getElementToSubelement(type, ghost_type); // loop over segments for (UInt s = 0; s < nb_segments; ++s) { // determine the elements connected to the segment connected_elements.clear(); const std::vector<Element> & twoD_elements = segment_to_2Delement(s); if (spatial_dimension == 2) { // if 2D just take the elements connected to the segments connected_elements.insert(twoD_elements.begin(), twoD_elements.end()); } else if (spatial_dimension == 3) { // if 3D a second loop is needed to get to the 3D elements std::vector<Element>::const_iterator facet = twoD_elements.begin(); for (; facet != twoD_elements.end(); ++facet) { const std::vector<Element> & threeD_elements = mesh_facets.getElementToSubelement( facet->type, facet->ghost_type)(facet->element); connected_elements.insert(threeD_elements.begin(), threeD_elements.end()); } } // get the minimum processor rank associated to the connected // elements and verify if ghost and not ghost elements are // found Int minimum_rank = std::numeric_limits<Int>::max(); // two booleans saying if not ghost and ghost elements are found in the // loop bool ghost_found[2]; ghost_found[0] = false; ghost_found[1] = false; std::set<Element>::iterator connected_elements_it = connected_elements.begin(); for (; connected_elements_it != connected_elements.end(); ++connected_elements_it) { if (*connected_elements_it == ElementNull) continue; ghost_found[connected_elements_it->ghost_type] = true; const Array<UInt> & el_to_rank_array = element_to_rank( connected_elements_it->type, connected_elements_it->ghost_type); minimum_rank = std::min(minimum_rank, Int(el_to_rank_array(connected_elements_it->element))); } // if no ghost elements are found the segment is local if (!ghost_found[1]) segment_to_nodetype(s) = -1; // if no not ghost elements are found the segment is pure ghost else if (!ghost_found[0]) segment_to_nodetype(s) = -3; // if the minimum rank is equal to the local rank, the segment is master else if (local_rank == minimum_rank) segment_to_nodetype(s) = -2; // if the minimum rank is less than the local rank, the segment is slave else if (local_rank > minimum_rank) segment_to_nodetype(s) = minimum_rank; else AKANTU_DEBUG_ERROR("The local rank cannot be smaller than the " "minimum rank if both ghost and not ghost " "elements are found"); } } } } /* -------------------------------------------------------------------------- */ UInt MeshUtils::updateLocalMasterGlobalConnectivity(Mesh & mesh, UInt local_nb_new_nodes) { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int rank = comm.whoAmI(); Int nb_proc = comm.getNbProc(); if (nb_proc == 1) return local_nb_new_nodes; /// resize global ids array Array<UInt> & nodes_global_ids = mesh.getGlobalNodesIds(); UInt old_nb_nodes = mesh.getNbNodes() - local_nb_new_nodes; nodes_global_ids.resize(mesh.getNbNodes()); /// compute the number of global nodes based on the number of old nodes Vector<UInt> old_local_master_nodes(nb_proc); for (UInt n = 0; n < old_nb_nodes; ++n) if (mesh.isLocalOrMasterNode(n)) ++old_local_master_nodes(rank); comm.allGather(old_local_master_nodes); UInt old_global_nodes = std::accumulate(old_local_master_nodes.storage(), old_local_master_nodes.storage() + nb_proc, 0); /// compute amount of local or master doubled nodes Vector<UInt> local_master_nodes(nb_proc); for (UInt n = old_nb_nodes; n < mesh.getNbNodes(); ++n) if (mesh.isLocalOrMasterNode(n)) ++local_master_nodes(rank); comm.allGather(local_master_nodes); /// update global number of nodes UInt total_nb_new_nodes = std::accumulate( local_master_nodes.storage(), local_master_nodes.storage() + nb_proc, 0); if (total_nb_new_nodes == 0) return 0; /// set global ids of local and master nodes UInt starting_index = std::accumulate(local_master_nodes.storage(), local_master_nodes.storage() + rank, old_global_nodes); for (UInt n = old_nb_nodes; n < mesh.getNbNodes(); ++n) { if (mesh.isLocalOrMasterNode(n)) { nodes_global_ids(n) = starting_index; ++starting_index; } } MeshAccessor mesh_accessor(mesh); mesh_accessor.setNbGlobalNodes(old_global_nodes + total_nb_new_nodes); return total_nb_new_nodes; } /* -------------------------------------------------------------------------- */ // Deactivating -Wunused-parameter #if defined(__INTEL_COMPILER) //#pragma warning ( disable : 383 ) #elif defined(__clang__) // test clang to be sure that when we test for gnu it // is only gnu #elif (defined(__GNUC__) || defined(__GNUG__)) #define GCC_VERSION \ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #if GCC_VERSION > 40600 #pragma GCC diagnostic push #endif #pragma GCC diagnostic ignored "-Wunused-parameter" #endif /* -------------------------------------------------------------------------- */ void MeshUtils::updateElementalConnectivity( Mesh & mesh, UInt old_node, UInt new_node, const std::vector<Element> & element_list, __attribute__((unused)) const std::vector<Element> * facet_list) { AKANTU_DEBUG_IN(); ElementType el_type = _not_defined; GhostType gt_type = _casper; Array<UInt> * conn_elem = NULL; #if defined(AKANTU_COHESIVE_ELEMENT) const Array<Element> * cohesive_facets = NULL; #endif UInt nb_nodes_per_element = 0; UInt * n_update = NULL; for (UInt el = 0; el < element_list.size(); ++el) { const Element & elem = element_list[el]; if (elem.type == _not_defined) continue; if (elem.type != el_type || elem.ghost_type != gt_type) { el_type = elem.type; gt_type = elem.ghost_type; conn_elem = &mesh.getConnectivity(el_type, gt_type); nb_nodes_per_element = conn_elem->getNbComponent(); #if defined(AKANTU_COHESIVE_ELEMENT) if (elem.kind == _ek_cohesive) cohesive_facets = &mesh.getMeshFacets().getSubelementToElement(el_type, gt_type); #endif } #if defined(AKANTU_COHESIVE_ELEMENT) if (elem.kind == _ek_cohesive) { AKANTU_DEBUG_ASSERT( facet_list != NULL, "Provide a facet list in order to update cohesive elements"); /// loop over cohesive element's facets for (UInt f = 0, n = 0; f < 2; ++f, n += nb_nodes_per_element / 2) { const Element & facet = (*cohesive_facets)(elem.element, f); /// skip facets if not present in the list if (std::find(facet_list->begin(), facet_list->end(), facet) == facet_list->end()) continue; n_update = std::find( conn_elem->storage() + elem.element * nb_nodes_per_element + n, conn_elem->storage() + elem.element * nb_nodes_per_element + n + nb_nodes_per_element / 2, old_node); AKANTU_DEBUG_ASSERT(n_update != conn_elem->storage() + elem.element * nb_nodes_per_element + n + nb_nodes_per_element / 2, "Node not found in current element"); /// update connectivity *n_update = new_node; } } else { #endif n_update = std::find(conn_elem->storage() + elem.element * nb_nodes_per_element, conn_elem->storage() + elem.element * nb_nodes_per_element + nb_nodes_per_element, old_node); AKANTU_DEBUG_ASSERT(n_update != conn_elem->storage() + elem.element * nb_nodes_per_element + nb_nodes_per_element, "Node not found in current element"); /// update connectivity *n_update = new_node; #if defined(AKANTU_COHESIVE_ELEMENT) } #endif } AKANTU_DEBUG_OUT(); } // Reactivating -Wunused-parameter #if defined(__INTEL_COMPILER) //#pragma warning ( disable : 383 ) #elif defined(__clang__) // test clang to be sure that when we test for gnu it // is only gnu #elif defined(__GNUG__) #if GCC_VERSION > 40600 #pragma GCC diagnostic pop #else #pragma GCC diagnostic warning "-Wunused-parameter" #endif #endif /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu // LocalWords: ElementType diff --git a/src/mesh_utils/mesh_utils.hh b/src/mesh_utils/mesh_utils.hh index 329ed0586..2c79aaa1a 100644 --- a/src/mesh_utils/mesh_utils.hh +++ b/src/mesh_utils/mesh_utils.hh @@ -1,244 +1,244 @@ /** * @file mesh_utils.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Dana Christen <dana.christen@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Oct 02 2015 * * @brief All mesh utils necessary for various tasks * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "aka_csr.hh" /* -------------------------------------------------------------------------- */ #include <vector> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_UTILS_HH__ #define __AKANTU_MESH_UTILS_HH__ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class MeshUtils { /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// build a CSR<UInt> that contains for each node the linearized number of /// the connected elements of a given spatial dimension static void buildNode2Elements(const Mesh & mesh, CSR<UInt> & node_to_elem, UInt spatial_dimension = _all_dimensions); /// build a CSR<Element> that contains for each node the list of connected /// elements of a given spatial dimension static void buildNode2Elements(const Mesh & mesh, CSR<Element> & node_to_elem, UInt spatial_dimension = _all_dimensions); /// build a CSR<UInt> that contains for each node the number of /// the connected elements of a given ElementType static void buildNode2ElementsElementTypeMap(const Mesh & mesh, CSR<UInt> & node_to_elem, const ElementType & type, const GhostType & ghost_type = _not_ghost); /// build the facets elements on the boundaries of a mesh static void buildFacets(Mesh & mesh); /// build all the facets elements: boundary and internals and store them in /// the mesh_facets for element of dimension from_dimension to to_dimension static void buildAllFacets(const Mesh & mesh, Mesh & mesh_facets, UInt from_dimension, UInt to_dimension); /// build all the facets elements: boundary and internals and store them in /// the mesh_facets static void buildAllFacets(const Mesh & mesh, Mesh & mesh_facets, UInt to_dimension = 0); /// build facets for a given spatial dimension static void buildFacetsDimension( const Mesh & mesh, Mesh & mesh_facets, bool boundary_only, UInt dimension, const ElementTypeMapArray<UInt> * prank_to_element = nullptr); /// take the local_connectivity array as the array of local and ghost /// connectivity, renumber the nodes and set the connectivity of the mesh static void renumberMeshNodes(Mesh & mesh, Array<UInt> & local_connectivities, UInt nb_local_element, UInt nb_ghost_element, ElementType type, Array<UInt> & old_nodes); /// compute pbc pair for a given direction static void computePBCMap(const Mesh & mymesh, const UInt dir, std::map<UInt, UInt> & pbc_pair); /// compute pbc pair for a surface pair static void computePBCMap(const Mesh & mymesh, const std::pair<Surface, Surface> & surface_pair, std::map<UInt, UInt> & pbc_pair); /// remove not connected nodes /!\ this functions renumbers the nodes. static void purifyMesh(Mesh & mesh); #if defined(AKANTU_COHESIVE_ELEMENT) /// function to insert cohesive elements on the selected facets /// @return number of facets that have been doubled static UInt insertCohesiveElements(Mesh & mesh, Mesh & mesh_facets, const ElementTypeMapArray<bool> & facet_insertion, Array<UInt> & doubled_nodes, Array<Element> & new_elements, bool only_double_facets); #endif /// fill the subelement to element and the elements to subelements data static void fillElementToSubElementsData(Mesh & mesh); /// flip facets based on global connectivity static void flipFacets(Mesh & mesh_facets, const ElementTypeMapArray<UInt> & global_connectivity, GhostType gt_facet); /// provide list of elements around a node and check if a given /// facet is reached template <bool third_dim_points> static bool findElementsAroundSubfacet( const Mesh & mesh, const Mesh & mesh_facets, const Element & starting_element, const Element & end_facet, const Vector<UInt> & subfacet_connectivity, std::vector<Element> & elem_list, std::vector<Element> & facet_list, std::vector<Element> * subfacet_list = nullptr); /// function to check if a node belongs to a given element static inline bool hasElement(const Array<UInt> & connectivity, const Element & el, const Vector<UInt> & nodes); /// reset facet_to_double arrays in the Mesh static void resetFacetToDouble(Mesh & mesh_facets); /// associate a node type to each segment in the mesh static void buildSegmentToNodeType(const Mesh & mesh, Mesh & mesh_facets); /// update local and master global connectivity when new nodes are added static UInt updateLocalMasterGlobalConnectivity(Mesh & mesh, UInt old_nb_nodes); private: /// match pairs that are on the associated pbc's static void matchPBCPairs(const Mesh & mymesh, const UInt dir, Array<UInt> & selected_left, Array<UInt> & selected_right, std::map<UInt, UInt> & pbc_pair); /// function used by all the renumbering functions static void renumberNodesInConnectivity(Array<UInt> & list_nodes, UInt nb_nodes, std::map<UInt, UInt> & renumbering_map); /// update facet_to_subfacet static void updateFacetToSubfacet(Mesh & mesh_facets, ElementType type_subfacet, GhostType gt_subfacet, bool facet_mode); /// update subfacet_to_facet static void updateSubfacetToFacet(Mesh & mesh_facets, ElementType type_subfacet, GhostType gt_subfacet, bool facet_mode); /// function to double a given facet and update the list of doubled /// nodes static void doubleFacet(Mesh & mesh, Mesh & mesh_facets, UInt facet_dimension, Array<UInt> & doubled_nodes, bool facet_mode); /// function to double a subfacet given start and end index for /// local facet_to_subfacet vector, and update the list of doubled /// nodes template <UInt spatial_dimension> static void doubleSubfacet(Mesh & mesh, Mesh & mesh_facets, Array<UInt> & doubled_nodes); /// double a node static void doubleNodes(Mesh & mesh, const std::vector<UInt> & old_nodes, Array<UInt> & doubled_nodes); /// fill facet_to_double array in the mesh /// returns the number of facets to be doubled static UInt updateFacetToDouble(Mesh & mesh_facets, const ElementTypeMapArray<bool> & facet_insertion); /// find subfacets to be doubled template <bool subsubfacet_mode> static void findSubfacetToDouble(Mesh & mesh, Mesh & mesh_facets); /// double facets (points) in 1D static void doublePointFacet(Mesh & mesh, Mesh & mesh_facets, Array<UInt> & doubled_nodes); #if defined(AKANTU_COHESIVE_ELEMENT) /// update cohesive element data static void updateCohesiveData(Mesh & mesh, Mesh & mesh_facets, Array<Element> & new_elements); #endif /// update elemental connectivity after doubling a node inline static void updateElementalConnectivity(Mesh & mesh, UInt old_node, UInt new_node, const std::vector<Element> & element_list, const std::vector<Element> * facet_list = NULL); /// double middle nodes if facets are _segment_3 template <bool third_dim_segments> static void updateQuadraticSegments(Mesh & mesh, Mesh & mesh_facets, ElementType type_facet, GhostType gt_facet, Array<UInt> & doubled_nodes); /// remove elements on a vector inline static bool removeElementsInVector(const std::vector<Element> & elem_to_remove, std::vector<Element> & elem_list); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "mesh_utils_inline_impl.cc" -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MESH_UTILS_HH__ */ diff --git a/src/mesh_utils/mesh_utils_pbc.cc b/src/mesh_utils/mesh_utils_pbc.cc index ea00ebf40..bc11d7891 100644 --- a/src/mesh_utils/mesh_utils_pbc.cc +++ b/src/mesh_utils/mesh_utils_pbc.cc @@ -1,298 +1,298 @@ /** * @file mesh_utils_pbc.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * * @date creation: Wed Feb 09 2011 * @date last modification: Tue Sep 15 2015 * * @brief periodic boundary condition connectivity tweak * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <map> /* -------------------------------------------------------------------------- */ #include "element_group.hh" #include "mesh_accessor.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /// class that sorts a set of nodes of same coordinates in 'dir' direction class CoordinatesComparison { public: CoordinatesComparison(const UInt dimension, const UInt dir_1, const UInt dir_2, Real normalization, Real tolerance, const Array<Real> & coords) : dim(dimension), dir_1(dir_1), dir_2(dir_2), normalization(normalization), tolerance(tolerance), coords_it(coords.begin(dim)) {} // answers the question whether n2 is larger or equal to n1 bool operator()(const UInt n1, const UInt n2) { Vector<Real> coords_n1 = coords_it[n1]; Vector<Real> coords_n2 = coords_it[n2]; return this->operator()(coords_n1, coords_n2); } bool operator()(const Vector<Real> & coords_n1, const Vector<Real> & coords_n2) { Real diff = coords_n1(dir_1) - coords_n2(dir_1);; if (dim == 2 || std::abs(diff) / normalization > tolerance) return diff > 0. ? false : true; else if (dim > 2) { diff = coords_n1(dir_2) - coords_n2(dir_2);; return diff > 0 ? false : true; } return true; } private: UInt dim; UInt dir_1; UInt dir_2; Real normalization; Real tolerance; const Array<Real>::const_vector_iterator coords_it; }; /* -------------------------------------------------------------------------- */ void MeshUtils::computePBCMap(const Mesh & mesh, const UInt dir, std::map<UInt, UInt> & pbc_pair) { Array<UInt> selected_left; Array<UInt> selected_right; const UInt dim = mesh.getSpatialDimension(); Array<Real>::const_vector_iterator it = mesh.getNodes().begin(dim); Array<Real>::const_vector_iterator end = mesh.getNodes().end(dim); if (dim <= dir) return; const Vector<Real> & lower_bounds = mesh.getLowerBounds(); const Vector<Real> & upper_bounds = mesh.getUpperBounds(); AKANTU_DEBUG_INFO("min " << lower_bounds(dir)); AKANTU_DEBUG_INFO("max " << upper_bounds(dir)); for (UInt node = 0; it != end; ++it, ++node) { const Vector<Real> & coords = *it; AKANTU_DEBUG_TRACE("treating " << coords(dir)); if (Math::are_float_equal(coords(dir), lower_bounds(dir))) { AKANTU_DEBUG_TRACE("pushing node " << node << " on the left side"); selected_left.push_back(node); } else if (Math::are_float_equal(coords(dir), upper_bounds(dir))) { selected_right.push_back(node); AKANTU_DEBUG_TRACE("pushing node " << node << " on the right side"); } } AKANTU_DEBUG_INFO( "found " << selected_left.getSize() << " and " << selected_right.getSize() << " nodes at each boundary for direction " << dir); // match pairs MeshUtils::matchPBCPairs(mesh, dir, selected_left, selected_right, pbc_pair); } /* -------------------------------------------------------------------------- */ void MeshUtils::computePBCMap(const Mesh & mesh, const SurfacePair & surface_pair, std::map<UInt, UInt> & pbc_pair) { Array<UInt> selected_first; Array<UInt> selected_second; // find nodes on surfaces const ElementGroup & first_surf = mesh.getElementGroup(surface_pair.first); const ElementGroup & second_surf = mesh.getElementGroup(surface_pair.second); // if this surface pair is not on this proc if (first_surf.getNbNodes() == 0 || second_surf.getNbNodes() == 0) { AKANTU_DEBUG_WARNING("computePBCMap has at least one surface without any " "nodes. I will ignore it."); return; } // copy nodes from element group selected_first.copy(first_surf.getNodeGroup().getNodes()); selected_second.copy(second_surf.getNodeGroup().getNodes()); // coordinates const Array<Real> & coords = mesh.getNodes(); const UInt dim = mesh.getSpatialDimension(); // variables to find min and max of surfaces Real first_max[3], first_min[3]; Real second_max[3], second_min[3]; for (UInt i = 0; i < dim; ++i) { first_min[i] = std::numeric_limits<Real>::max(); second_min[i] = std::numeric_limits<Real>::max(); first_max[i] = -std::numeric_limits<Real>::max(); second_max[i] = -std::numeric_limits<Real>::max(); } // find min and max of surface nodes for (Array<UInt>::scalar_iterator it = selected_first.begin(); it != selected_first.end(); ++it) { for (UInt i = 0; i < dim; ++i) { if (first_min[i] > coords(*it, i)) first_min[i] = coords(*it, i); if (first_max[i] < coords(*it, i)) first_max[i] = coords(*it, i); } } for (Array<UInt>::scalar_iterator it = selected_second.begin(); it != selected_second.end(); ++it) { for (UInt i = 0; i < dim; ++i) { if (second_min[i] > coords(*it, i)) second_min[i] = coords(*it, i); if (second_max[i] < coords(*it, i)) second_max[i] = coords(*it, i); } } // find direction of pbc Int first_dir = -1; #ifndef AKANTU_NDEBUG Int second_dir = -2; #endif for (UInt i = 0; i < dim; ++i) { if (Math::are_float_equal(first_min[i], first_max[i])) { first_dir = i; } #ifndef AKANTU_NDEBUG if (Math::are_float_equal(second_min[i], second_max[i])) { second_dir = i; } #endif } AKANTU_DEBUG_ASSERT(first_dir == second_dir, "Surface pair has not same direction. Surface " << surface_pair.first << " dir=" << first_dir << " ; Surface " << surface_pair.second << " dir=" << second_dir); UInt dir = first_dir; // match pairs if (first_min[dir] < second_min[dir]) MeshUtils::matchPBCPairs(mesh, dir, selected_first, selected_second, pbc_pair); else MeshUtils::matchPBCPairs(mesh, dir, selected_second, selected_first, pbc_pair); } /* -------------------------------------------------------------------------- */ void MeshUtils::matchPBCPairs(const Mesh & mesh, const UInt dir, Array<UInt> & selected_left, Array<UInt> & selected_right, std::map<UInt, UInt> & pbc_pair) { // tolerance is that large because most meshers generate points coordinates // with single precision only (it is the case of GMSH for instance) Real tolerance = 1e-7; const UInt dim = mesh.getSpatialDimension(); Real normalization = mesh.getUpperBounds()(dir) - mesh.getLowerBounds()(dir); AKANTU_DEBUG_ASSERT(std::abs(normalization) > Math::getTolerance(), "In matchPBCPairs: The normalization is zero. " << "Did you compute the bounding box of the mesh?"); UInt odir_1 = UInt(-1), odir_2 = UInt(-1); if (dim == 3) { if (dir == _x) { odir_1 = _y; odir_2 = _z; } else if (dir == _y) { odir_1 = _x; odir_2 = _z; } else if (dir == _z) { odir_1 = _x; odir_2 = _y; } } else if (dim == 2) { if (dir == _x) { odir_1 = _y; } else if (dir == _y) { odir_1 = _x; } } CoordinatesComparison compare_nodes(dim, odir_1, odir_2, normalization, tolerance, mesh.getNodes()); std::sort(selected_left.begin(), selected_left.end(), compare_nodes); std::sort(selected_right.begin(), selected_right.end(), compare_nodes); Array<UInt>::scalar_iterator it_left = selected_left.begin(); Array<UInt>::scalar_iterator end_left = selected_left.end(); Array<UInt>::scalar_iterator it_right = selected_right.begin(); Array<UInt>::scalar_iterator end_right = selected_right.end(); Array<Real>::const_vector_iterator nit = mesh.getNodes().begin(dim); while ((it_left != end_left) && (it_right != end_right)) { UInt i1 = *it_left; UInt i2 = *it_right; Vector<Real> coords1 = nit[i1]; Vector<Real> coords2 = nit[i2]; AKANTU_DEBUG_TRACE("do I pair? " << i1 << "(" << coords1 << ") with" << i2 << "(" << coords2 << ") in direction " << dir); Real dx = 0.0; Real dy = 0.0; if (dim >= 2) dx = coords1(odir_1) - coords2(odir_1); if (dim == 3) dy = coords1(odir_2) - coords2(odir_2); if (std::abs(dx * dx + dy * dy) / normalization < tolerance) { // then i match these pairs if (pbc_pair.count(i2)) { i2 = pbc_pair[i2]; } pbc_pair[i1] = i2; AKANTU_DEBUG_TRACE("pairing " << i1 << "(" << coords1 << ") with" << i2 << "(" << coords2 << ") in direction " << dir); ++it_left; ++it_right; } else if (compare_nodes(coords1, coords2)) { ++it_left; } else { ++it_right; } } AKANTU_DEBUG_INFO("found " << pbc_pair.size() << " pairs for direction " << dir); } -__END_AKANTU__ +} // akantu diff --git a/src/model/boundary_condition.hh b/src/model/boundary_condition.hh index 26543509c..ed18419b2 100644 --- a/src/model/boundary_condition.hh +++ b/src/model/boundary_condition.hh @@ -1,106 +1,106 @@ /** * @file boundary_condition.hh * * @author Dana Christen <dana.christen@gmail.com> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Dec 18 2015 * * @brief XXX * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_BOUNDARY_CONDITION_HH__ #define __AKANTU_BOUNDARY_CONDITION_HH__ #include "aka_common.hh" #include "boundary_condition_functor.hh" #include "mesh.hh" #include "fe_engine.hh" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { template <class ModelType> class BoundaryCondition { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ private: /* ------------------------------------------------------------------------ */ /* Constructors / Destructors / Initializers */ /* ------------------------------------------------------------------------ */ public: BoundaryCondition() : model(NULL), primal(NULL), dual(NULL), primal_increment(NULL) {} ///Initialize the boundary conditions void initBC(ModelType & ptr, Array<Real> & primal, Array<Real> & dual); void initBC(ModelType & ptr, Array<Real> & primal, Array<Real> & primal_increment, Array<Real> & dual); /* ------------------------------------------------------------------------ */ /* Methods and accessors */ /* ------------------------------------------------------------------------ */ public: //inline void initBoundaryCondition(); template<typename FunctorType> ///Apply the boundary conditions inline void applyBC(const FunctorType & func); template<class FunctorType> inline void applyBC(const FunctorType & func, const std::string & group_name); template<class FunctorType> inline void applyBC(const FunctorType & func, const ElementGroup & element_group); AKANTU_GET_MACRO_NOT_CONST(Model, *model, ModelType &); AKANTU_GET_MACRO_NOT_CONST(Primal,*primal, Array<Real> &); AKANTU_GET_MACRO_NOT_CONST(Dual, *dual, Array<Real> &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: template<class FunctorType, BC::Functor::Type type = FunctorType::type> struct TemplateFunctionWrapper; private: ModelType * model; Array<Real> * primal; Array<Real> * dual; Array<Real> * primal_increment; }; -__END_AKANTU__ +} // akantu #include "boundary_condition_tmpl.hh" #endif /* __AKANTU_BOUNDARY_CONDITION_HH__ */ diff --git a/src/model/boundary_condition_functor.hh b/src/model/boundary_condition_functor.hh index 92aee20bc..cbc7358d8 100644 --- a/src/model/boundary_condition_functor.hh +++ b/src/model/boundary_condition_functor.hh @@ -1,197 +1,197 @@ /** * @file boundary_condition_functor.hh * * @author Dana Christen <dana.christen@gmail.com> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri May 03 2013 * @date last modification: Thu Oct 15 2015 * * @brief Definitions of the functors to apply boundary conditions * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fe_engine.hh" #include "integration_point.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_BOUNDARY_CONDITION_FUNCTOR_HH__ #define __AKANTU_BOUNDARY_CONDITION_FUNCTOR_HH__ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ namespace BC { typedef ::akantu::SpacialDirection Axis; struct Functor { enum Type { _dirichlet, _neumann }; }; /* ------------------------------------------------------------------------ */ /* Dirichlet */ /* ------------------------------------------------------------------------ */ namespace Dirichlet { /* ---------------------------------------------------------------------- */ class DirichletFunctor : public Functor { protected: DirichletFunctor() : axis(_x) {} explicit DirichletFunctor(Axis ax) : axis(ax) {} public: void operator()(__attribute__((unused)) UInt node, __attribute__((unused)) Vector<bool> & flags, __attribute__((unused)) Vector<Real> & primal, __attribute__((unused)) const Vector<Real> & coord) const { AKANTU_DEBUG_TO_IMPLEMENT(); } public: static const Type type = _dirichlet; protected: Axis axis; }; /* ---------------------------------------------------------------------- */ class FlagOnly : public DirichletFunctor { public: explicit FlagOnly(Axis ax = _x) : DirichletFunctor(ax) {} public: inline void operator()(UInt node, Vector<bool> & flags, Vector<Real> & primal, const Vector<Real> & coord) const; }; /* ---------------------------------------------------------------------- */ class FreeBoundary : public DirichletFunctor { public: explicit FreeBoundary(Axis ax = _x) : DirichletFunctor(ax) {} public: inline void operator()(UInt node, Vector<bool> & flags, Vector<Real> & primal, const Vector<Real> & coord) const; }; /* ---------------------------------------------------------------------- */ class FixedValue : public DirichletFunctor { public: FixedValue(Real val, Axis ax = _x) : DirichletFunctor(ax), value(val) {} public: inline void operator()(UInt node, Vector<bool> & flags, Vector<Real> & primal, const Vector<Real> & coord) const; protected: Real value; }; /* ---------------------------------------------------------------------- */ class IncrementValue : public DirichletFunctor { public: IncrementValue(Real val, Axis ax = _x) : DirichletFunctor(ax), value(val) {} public: inline void operator()(UInt node, Vector<bool> & flags, Vector<Real> & primal, const Vector<Real> & coord) const; inline void setIncrement(Real val) { this->value = val; } protected: Real value; }; } // end namespace Dirichlet /* ------------------------------------------------------------------------ */ /* Neumann */ /* ------------------------------------------------------------------------ */ namespace Neumann { /* ---------------------------------------------------------------------- */ class NeumannFunctor : public Functor { protected: NeumannFunctor() {} public: virtual void operator()(const IntegrationPoint & quad_point, Vector<Real> & dual, const Vector<Real> & coord, const Vector<Real> & normals) const = 0; virtual ~NeumannFunctor() {} public: static const Type type = _neumann; }; /* ---------------------------------------------------------------------- */ class FromHigherDim : public NeumannFunctor { public: explicit FromHigherDim(const Matrix<Real> & mat) : bc_data(mat) {} virtual ~FromHigherDim() {} public: inline void operator()(const IntegrationPoint & quad_point, Vector<Real> & dual, const Vector<Real> & coord, const Vector<Real> & normals) const; protected: Matrix<Real> bc_data; }; /* ---------------------------------------------------------------------- */ class FromSameDim : public NeumannFunctor { public: explicit FromSameDim(const Vector<Real> & vec) : bc_data(vec) {} virtual ~FromSameDim() {} public: inline void operator()(const IntegrationPoint & quad_point, Vector<Real> & dual, const Vector<Real> & coord, const Vector<Real> & normals) const; protected: Vector<Real> bc_data; }; /* ---------------------------------------------------------------------- */ class FreeBoundary : public NeumannFunctor { public: inline void operator()(const IntegrationPoint & quad_point, Vector<Real> & dual, const Vector<Real> & coord, const Vector<Real> & normals) const; }; } // end namespace Neumann } // end namespace BC -__END_AKANTU__ +} // akantu #include "boundary_condition_functor_inline_impl.cc" #endif /* __AKANTU_BOUNDARY_CONDITION_FUNCTOR_HH__ */ diff --git a/src/model/boundary_condition_functor_inline_impl.cc b/src/model/boundary_condition_functor_inline_impl.cc index 712363225..fd76c9510 100644 --- a/src/model/boundary_condition_functor_inline_impl.cc +++ b/src/model/boundary_condition_functor_inline_impl.cc @@ -1,139 +1,139 @@ /** * @file boundary_condition_functor_inline_impl.cc * * @author Dana Christen <dana.christen@gmail.com> * * @date creation: Fri May 03 2013 * @date last modification: Thu Oct 15 2015 * * @brief implementation of the BC::Functors * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #define DIRICHLET_SANITY_CHECK \ AKANTU_DEBUG_ASSERT( \ coord.size() <= flags.size(), \ "The coordinates and flags vectors given to the boundary" \ << " condition functor have different sizes!"); \ AKANTU_DEBUG_ASSERT( \ primal.size() <= coord.size(), \ "The primal vector and coordinates vector given" \ << " to the boundary condition functor have different sizes!"); #define NEUMANN_SANITY_CHECK \ AKANTU_DEBUG_ASSERT( \ coord.size() <= normals.size(), \ "The coordinates and normals vectors given to the" \ << " boundary condition functor have different sizes!"); \ AKANTU_DEBUG_ASSERT( \ dual.size() <= coord.size(), \ "The dual vector and coordinates vector given to" \ << " the boundary condition functor have different sizes!"); -__BEGIN_AKANTU__ +namespace akantu { namespace BC { namespace Dirichlet { /* ------------------------------------------------------------------------ */ inline void FlagOnly::operator()(__attribute__((unused)) UInt node, Vector<bool> & flags, __attribute__((unused)) Vector<Real> & primal, __attribute__((unused)) const Vector<Real> & coord) const { DIRICHLET_SANITY_CHECK; flags(this->axis) = true; } /* ------------------------------------------------------------------------ */ inline void FreeBoundary:: operator()(__attribute__((unused)) UInt node, Vector<bool> & flags, __attribute__((unused)) Vector<Real> & primal, __attribute__((unused)) const Vector<Real> & coord) const { DIRICHLET_SANITY_CHECK; flags(this->axis) = false; } /* ------------------------------------------------------------------------ */ inline void FixedValue::operator()(__attribute__((unused)) UInt node, Vector<bool> & flags, Vector<Real> & primal, __attribute__((unused)) const Vector<Real> & coord) const { DIRICHLET_SANITY_CHECK; flags(this->axis) = true; primal(this->axis) = value; } /* ------------------------------------------------------------------------ */ inline void IncrementValue::operator()(__attribute__((unused)) UInt node, Vector<bool> & flags, Vector<Real> & primal, __attribute__((unused)) const Vector<Real> & coord) const { DIRICHLET_SANITY_CHECK; flags(this->axis) = true; primal(this->axis) += value; } } // end namespace Dirichlet /* -------------------------------------------------------------------------- */ /* Neumann */ /* -------------------------------------------------------------------------- */ namespace Neumann { /* ------------------------------------------------------------------------ */ inline void FreeBoundary:: operator()(__attribute__((unused)) const IntegrationPoint & quad_point, Vector<Real> & dual, __attribute__((unused)) const Vector<Real> & coord, __attribute__((unused)) const Vector<Real> & normals) const { for (UInt i(0); i < dual.size(); ++i) { dual(i) = 0.0; } } /* ------------------------------------------------------------------------ */ inline void FromHigherDim::operator()(__attribute__((unused)) const IntegrationPoint & quad_point, Vector<Real> & dual, __attribute__((unused)) const Vector<Real> & coord, const Vector<Real> & normals) const { dual.mul<false>(this->bc_data, normals); } /* ------------------------------------------------------------------------ */ inline void FromSameDim:: operator()(__attribute__((unused)) const IntegrationPoint & quad_point, Vector<Real> & dual, __attribute__((unused)) const Vector<Real> & coord, __attribute__((unused)) const Vector<Real> & normals) const { dual = this->bc_data; } } // end namespace Neumann } // end namespace BC -__END_AKANTU__ +} // akantu diff --git a/src/model/boundary_condition_python_functor.cc b/src/model/boundary_condition_python_functor.cc index cae69819a..fbaf982cd 100644 --- a/src/model/boundary_condition_python_functor.cc +++ b/src/model/boundary_condition_python_functor.cc @@ -1,66 +1,66 @@ /** * @file boundary_condition_python_functor.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * * @date creation: Wed Aug 31 2011 * @date last modification: Fri Nov 13 2015 * * @brief Interface for BC::Functor written in python * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "boundary_condition_python_functor.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { namespace BC { void PythonFunctorDirichlet::operator ()(UInt node, Vector<bool> & flags, Vector<Real> & primal, const Vector<Real> & coord) const{ this->callFunctor<void>("operator",node,flags,primal,coord); } void PythonFunctorNeumann::operator()(const IntegrationPoint & quad_point, Vector<Real> & dual, const Vector<Real> & coord, const Vector<Real> & normals) const{ this->callFunctor<void>("operator",quad_point,dual,coord,normals); } }//end namespace BC -__END_AKANTU__ +} // akantu diff --git a/src/model/boundary_condition_python_functor.hh b/src/model/boundary_condition_python_functor.hh index ff93856d5..50549bd2b 100644 --- a/src/model/boundary_condition_python_functor.hh +++ b/src/model/boundary_condition_python_functor.hh @@ -1,116 +1,116 @@ /** * @file boundary_condition_python_functor.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Fri Nov 13 2015 * * @brief interface for BC::Functor writen in python * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "boundary_condition_functor.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_BOUNDARY_CONDITION_PYTHON_FUNCTOR_HH__ #define __AKANTU_BOUNDARY_CONDITION_PYTHON_FUNCTOR_HH__ /* -------------------------------------------------------------------------- */ #include "boundary_condition_functor.hh" #include "python_functor.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { namespace BC { class PythonFunctorDirichlet : public PythonFunctor, public Functor { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: PythonFunctorDirichlet(PyObject * obj) : PythonFunctor(obj) {} /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void operator()(UInt node, Vector<bool> & flags, Vector<Real> & primal, const Vector<Real> & coord) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: static const Type type = _dirichlet; }; /* -------------------------------------------------------------------------- */ class PythonFunctorNeumann : public PythonFunctor, public Functor{ /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: PythonFunctorNeumann(PyObject * obj) : PythonFunctor(obj) {} /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void operator()(const IntegrationPoint & quad_point, Vector<Real> & dual, const Vector<Real> & coord, const Vector<Real> & normals) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: static const Type type = _neumann; }; }//end namespace BC -__END_AKANTU__ +} // akantu #endif /* __AKANTU_BOUNDARY_CONDITION_PYTHON_FUNCTOR_HH__ */ diff --git a/src/model/boundary_condition_tmpl.hh b/src/model/boundary_condition_tmpl.hh index 299e35fe5..4957dd61e 100644 --- a/src/model/boundary_condition_tmpl.hh +++ b/src/model/boundary_condition_tmpl.hh @@ -1,270 +1,270 @@ /** * @file boundary_condition_tmpl.hh * * @author Dana Christen <dana.christen@gmail.com> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri May 03 2013 * @date last modification: Fri Oct 16 2015 * * @brief implementation of the applyBC * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "element_group.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <typename ModelType> void BoundaryCondition<ModelType>::initBC(ModelType & model, Array<Real> & primal, Array<Real> & dual) { this->model = &model; this->primal = &primal; this->dual = &dual; if (this->model->getSpatialDimension() > 1) this->model->initFEEngineBoundary(); } /* -------------------------------------------------------------------------- */ template <typename ModelType> void BoundaryCondition<ModelType>::initBC(ModelType & model, Array<Real> & primal, Array<Real> & primal_increment, Array<Real> & dual) { this->initBC(model, primal, dual); this->primal_increment = &primal_increment; } /* -------------------------------------------------------------------------- */ /* Partial specialization for DIRICHLET functors */ template <typename ModelType> template <typename FunctorType> struct BoundaryCondition<ModelType>::TemplateFunctionWrapper< FunctorType, BC::Functor::_dirichlet> { static inline void applyBC(const FunctorType & func, const ElementGroup & group, BoundaryCondition<ModelType> & bc_instance) { ModelType & model = bc_instance.getModel(); Array<Real> & primal = bc_instance.getPrimal(); const Array<Real> & coords = model.getMesh().getNodes(); Array<bool> & boundary_flags = model.getBlockedDOFs(); UInt dim = model.getMesh().getSpatialDimension(); Array<Real>::vector_iterator primal_iter = primal.begin(primal.getNbComponent()); Array<Real>::const_vector_iterator coords_iter = coords.begin(dim); Array<bool>::vector_iterator flags_iter = boundary_flags.begin(boundary_flags.getNbComponent()); for (ElementGroup::const_node_iterator nodes_it(group.node_begin()); nodes_it != group.node_end(); ++nodes_it) { UInt n = *nodes_it; Vector<bool> flag(flags_iter[n]); Vector<Real> primal(primal_iter[n]); Vector<Real> coords(coords_iter[n]); func(n, flag, primal, coords); } } }; /* -------------------------------------------------------------------------- */ /* Partial specialization for NEUMANN functors */ template <typename ModelType> template <typename FunctorType> struct BoundaryCondition<ModelType>::TemplateFunctionWrapper< FunctorType, BC::Functor::_neumann> { static inline void applyBC(const FunctorType & func, const ElementGroup & group, BoundaryCondition<ModelType> & bc_instance) { UInt dim = bc_instance.getModel().getSpatialDimension(); switch (dim) { case 1: { AKANTU_DEBUG_TO_IMPLEMENT(); break; } case 2: case 3: { applyBC(func, group, bc_instance, _not_ghost); applyBC(func, group, bc_instance, _ghost); break; } } } static inline void applyBC(const FunctorType & func, const ElementGroup & group, BoundaryCondition<ModelType> & bc_instance, GhostType ghost_type) { ModelType & model = bc_instance.getModel(); Array<Real> & dual = bc_instance.getDual(); const Mesh & mesh = model.getMesh(); const Array<Real> & nodes_coords = mesh.getNodes(); const FEEngine & fem_boundary = model.getFEEngineBoundary(); UInt dim = model.getSpatialDimension(); UInt nb_degree_of_freedom = dual.getNbComponent(); IntegrationPoint quad_point; quad_point.ghost_type = ghost_type; ElementGroup::type_iterator type_it = group.firstType(dim - 1, ghost_type); ElementGroup::type_iterator type_end = group.lastType(dim - 1, ghost_type); // Loop over the boundary element types for (; type_it != type_end; ++type_it) { const Array<UInt> & element_ids = group.getElements(*type_it, ghost_type); Array<UInt>::const_scalar_iterator elem_iter = element_ids.begin(); Array<UInt>::const_scalar_iterator elem_iter_end = element_ids.end(); UInt nb_quad_points = fem_boundary.getNbIntegrationPoints(*type_it, ghost_type); UInt nb_elements = element_ids.getSize(); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(*type_it); Array<Real> * dual_before_integ = new Array<Real>( nb_elements * nb_quad_points, nb_degree_of_freedom, 0.); Array<Real> * quad_coords = new Array<Real>(nb_elements * nb_quad_points, dim); const Array<Real> & normals_on_quad = fem_boundary.getNormalsOnIntegrationPoints(*type_it, ghost_type); fem_boundary.interpolateOnIntegrationPoints( nodes_coords, *quad_coords, dim, *type_it, ghost_type, element_ids); Array<Real>::const_vector_iterator normals_begin = normals_on_quad.begin(dim); Array<Real>::const_vector_iterator normals_iter; Array<Real>::const_vector_iterator quad_coords_iter = quad_coords->begin(dim); Array<Real>::vector_iterator dual_iter = dual_before_integ->begin(nb_degree_of_freedom); quad_point.type = *type_it; for (; elem_iter != elem_iter_end; ++elem_iter) { UInt el = *elem_iter; quad_point.element = el; normals_iter = normals_begin + el * nb_quad_points; for (UInt q(0); q < nb_quad_points; ++q) { quad_point.num_point = q; func(quad_point, *dual_iter, *quad_coords_iter, *normals_iter); ++dual_iter; ++quad_coords_iter; ++normals_iter; } } delete quad_coords; /* -------------------------------------------------------------------- */ // Initialization of iterators Array<Real>::matrix_iterator dual_iter_mat = dual_before_integ->begin(nb_degree_of_freedom, 1); elem_iter = element_ids.begin(); Array<Real>::const_matrix_iterator shapes_iter_begin = fem_boundary.getShapes(*type_it, ghost_type) .begin(1, nb_nodes_per_element); Array<Real> * dual_by_shapes = new Array<Real>(nb_elements * nb_quad_points, nb_degree_of_freedom * nb_nodes_per_element); Array<Real>::matrix_iterator dual_by_shapes_iter = dual_by_shapes->begin(nb_degree_of_freedom, nb_nodes_per_element); Array<Real>::const_matrix_iterator shapes_iter; /* -------------------------------------------------------------------- */ // Loop computing dual x shapes for (; elem_iter != elem_iter_end; ++elem_iter) { shapes_iter = shapes_iter_begin + *elem_iter * nb_quad_points; for (UInt q(0); q < nb_quad_points; ++q, ++dual_iter_mat, ++dual_by_shapes_iter, ++shapes_iter) { dual_by_shapes_iter->mul<false, false>(*dual_iter_mat, *shapes_iter); } } delete dual_before_integ; Array<Real> * dual_by_shapes_integ = new Array<Real>( nb_elements, nb_degree_of_freedom * nb_nodes_per_element); fem_boundary.integrate(*dual_by_shapes, *dual_by_shapes_integ, nb_degree_of_freedom * nb_nodes_per_element, *type_it, ghost_type, element_ids); delete dual_by_shapes; // assemble the result into force vector model.getDOFManager().assembleElementalArrayLocalArray( *dual_by_shapes_integ, dual, *type_it, ghost_type, 1., element_ids); delete dual_by_shapes_integ; } } }; /* -------------------------------------------------------------------------- */ template <typename ModelType> template <typename FunctorType> inline void BoundaryCondition<ModelType>::applyBC(const FunctorType & func) { GroupManager::const_element_group_iterator bit = model->getMesh().getGroupManager().element_group_begin(); GroupManager::const_element_group_iterator bend = model->getMesh().getGroupManager().element_group_end(); for (; bit != bend; ++bit) applyBC(func, *bit); } /* -------------------------------------------------------------------------- */ template <typename ModelType> template <typename FunctorType> inline void BoundaryCondition<ModelType>::applyBC(const FunctorType & func, const std::string & group_name) { try { const ElementGroup & element_group = model->getMesh().getElementGroup(group_name); applyBC(func, element_group); } catch (akantu::debug::Exception e) { AKANTU_EXCEPTION("Error applying a boundary condition onto \"" << group_name << "\"! [" << e.what() << "]"); } } /* -------------------------------------------------------------------------- */ template <typename ModelType> template <typename FunctorType> inline void BoundaryCondition<ModelType>::applyBC(const FunctorType & func, const ElementGroup & element_group) { #if !defined(AKANTU_NDEBUG) if (element_group.getDimension() != model->getSpatialDimension() - 1) AKANTU_DEBUG_WARNING("The group " << element_group.getName() << " does not contain only boundaries elements"); #endif TemplateFunctionWrapper<FunctorType>::applyBC(func, element_group, *this); } -__END_AKANTU__ +} // akantu diff --git a/src/model/common/neighborhood_base.cc b/src/model/common/neighborhood_base.cc index fd1852828..7f8858b9b 100644 --- a/src/model/common/neighborhood_base.cc +++ b/src/model/common/neighborhood_base.cc @@ -1,314 +1,314 @@ /** * @file neighborhood_base.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sat Sep 26 2015 * @date last modification: Wed Nov 25 2015 * * @brief Implementation of generic neighborhood base * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "neighborhood_base.hh" #include "grid_synchronizer.hh" #include "model.hh" /* -------------------------------------------------------------------------- */ #include <fstream> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ NeighborhoodBase::NeighborhoodBase(Model & model, const ElementTypeMapReal & quad_coordinates, const ID & id, const MemoryID & memory_id) : Memory(id, memory_id), model(model), neighborhood_radius(0.), spatial_grid(NULL), is_creating_grid(false), grid_synchronizer(NULL), quad_coordinates(quad_coordinates), spatial_dimension(this->model.getMesh().getSpatialDimension()) { AKANTU_DEBUG_IN(); this->registerDataAccessor(*this); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ NeighborhoodBase::~NeighborhoodBase() { AKANTU_DEBUG_IN(); delete spatial_grid; delete grid_synchronizer; AKANTU_DEBUG_OUT(); } // /* -------------------------------------------------------------------------- // */ // void NeighborhoodBase::createSynchronizerRegistry(DataAccessor * // data_accessor){ // this->synch_registry = new SynchronizerRegistry(*data_accessor); // } /* -------------------------------------------------------------------------- */ void NeighborhoodBase::initNeighborhood() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Creating the grid"); this->createGrid(); AKANTU_DEBUG_OUT(); } /* ------------------------------------------------------------------------- */ void NeighborhoodBase::createGrid() { AKANTU_DEBUG_IN(); const Real safety_factor = 1.2; // for the cell grid spacing Mesh & mesh = this->model.getMesh(); mesh.computeBoundingBox(); const Vector<Real> & lower_bounds = mesh.getLocalLowerBounds(); const Vector<Real> & upper_bounds = mesh.getLocalUpperBounds(); Vector<Real> center = 0.5 * (upper_bounds + lower_bounds); Vector<Real> spacing(spatial_dimension, this->neighborhood_radius * safety_factor); spatial_grid = new SpatialGrid<IntegrationPoint>(spatial_dimension, spacing, center); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void NeighborhoodBase::updatePairList() { AKANTU_DEBUG_IN(); //// loop over all quads -> all cells SpatialGrid<IntegrationPoint>::cells_iterator cell_it = spatial_grid->beginCells(); SpatialGrid<IntegrationPoint>::cells_iterator cell_end = spatial_grid->endCells(); Vector<Real> q1_coords(spatial_dimension); Vector<Real> q2_coords(spatial_dimension); IntegrationPoint q1; IntegrationPoint q2; UInt counter = 0; for (; cell_it != cell_end; ++cell_it) { AKANTU_DEBUG_INFO("Looping on next cell"); SpatialGrid<IntegrationPoint>::Cell::iterator first_quad = spatial_grid->beginCell(*cell_it); SpatialGrid<IntegrationPoint>::Cell::iterator last_quad = spatial_grid->endCell(*cell_it); for (; first_quad != last_quad; ++first_quad, ++counter) { q1 = *first_quad; if (q1.ghost_type == _ghost) break; Array<Real>::const_vector_iterator coords_type_1_it = this->quad_coordinates(q1.type, q1.ghost_type) .begin(spatial_dimension); q1_coords = coords_type_1_it[q1.global_num]; AKANTU_DEBUG_INFO("Current quadrature point in this cell: " << q1); SpatialGrid<IntegrationPoint>::CellID cell_id = spatial_grid->getCellID(q1_coords); /// loop over all the neighbouring cells of the current quad SpatialGrid<IntegrationPoint>::neighbor_cells_iterator first_neigh_cell = spatial_grid->beginNeighborCells(cell_id); SpatialGrid<IntegrationPoint>::neighbor_cells_iterator last_neigh_cell = spatial_grid->endNeighborCells(cell_id); for (; first_neigh_cell != last_neigh_cell; ++first_neigh_cell) { SpatialGrid<IntegrationPoint>::Cell::iterator first_neigh_quad = spatial_grid->beginCell(*first_neigh_cell); SpatialGrid<IntegrationPoint>::Cell::iterator last_neigh_quad = spatial_grid->endCell(*first_neigh_cell); // loop over the quadrature point in the current neighboring cell for (; first_neigh_quad != last_neigh_quad; ++first_neigh_quad) { q2 = *first_neigh_quad; Array<Real>::const_vector_iterator coords_type_2_it = this->quad_coordinates(q2.type, q2.ghost_type) .begin(spatial_dimension); q2_coords = coords_type_2_it[q2.global_num]; Real distance = q1_coords.distance(q2_coords); if (distance <= this->neighborhood_radius + Math::getTolerance() && (q2.ghost_type == _ghost || (q2.ghost_type == _not_ghost && q1.global_num <= q2.global_num))) { // storing only half lists pair_list[q2.ghost_type].push_back(std::make_pair(q1, q2)); } } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void NeighborhoodBase::savePairs(const std::string & filename) const { std::ofstream pout; std::stringstream sstr; StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int prank = comm.whoAmI(); sstr << filename << "." << prank; pout.open(sstr.str().c_str()); for (UInt gt = _not_ghost; gt <= _ghost; ++gt) { GhostType ghost_type2 = (GhostType)gt; PairList::const_iterator first_pair = pair_list[ghost_type2].begin(); PairList::const_iterator last_pair = pair_list[ghost_type2].end(); for (; first_pair != last_pair; ++first_pair) { const IntegrationPoint & q1 = first_pair->first; const IntegrationPoint & q2 = first_pair->second; pout << q1 << " " << q2 << " " << std::endl; } } } /* -------------------------------------------------------------------------- */ void NeighborhoodBase::saveNeighborCoords(const std::string & filename) const { /// this function is not optimazed and only used for tests on small meshes /// @todo maybe optimize this function for better performance? Vector<Real> q1_coords(spatial_dimension); Vector<Real> q2_coords(spatial_dimension); IntegrationPoint q1; IntegrationPoint q2; std::ofstream pout; std::stringstream sstr; StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int prank = comm.whoAmI(); sstr << filename << "." << prank; pout.open(sstr.str().c_str()); /// loop over all the quads and write the position of their neighbors SpatialGrid<IntegrationPoint>::cells_iterator cell_it = spatial_grid->beginCells(); SpatialGrid<IntegrationPoint>::cells_iterator cell_end = spatial_grid->endCells(); for (; cell_it != cell_end; ++cell_it) { SpatialGrid<IntegrationPoint>::Cell::iterator first_quad = spatial_grid->beginCell(*cell_it); SpatialGrid<IntegrationPoint>::Cell::iterator last_quad = spatial_grid->endCell(*cell_it); for (; first_quad != last_quad; ++first_quad) { q1 = *first_quad; Array<Real>::const_vector_iterator coords_type_1_it = this->quad_coordinates(q1.type, q1.ghost_type) .begin(spatial_dimension); q1_coords = coords_type_1_it[q1.global_num]; pout << "#neighbors for quad " << q1.global_num << std::endl; pout << q1_coords << std::endl; for (UInt gt = _not_ghost; gt <= _ghost; ++gt) { GhostType ghost_type2 = (GhostType)gt; PairList::const_iterator first_pair = pair_list[ghost_type2].begin(); PairList::const_iterator last_pair = pair_list[ghost_type2].end(); for (; first_pair != last_pair; ++first_pair) { if (q1 == first_pair->first && first_pair->second != q1) { q2 = first_pair->second; Array<Real>::const_vector_iterator coords_type_2_it = this->quad_coordinates(q2.type, q2.ghost_type) .begin(spatial_dimension); q2_coords = coords_type_2_it[q2.global_num]; pout << q2_coords << std::endl; } if (q1 == first_pair->second && first_pair->first != q1) { q2 = first_pair->first; Array<Real>::const_vector_iterator coords_type_2_it = this->quad_coordinates(q2.type, q2.ghost_type) .begin(spatial_dimension); q2_coords = coords_type_2_it[q2.global_num]; pout << q2_coords << std::endl; } } } } } } /* -------------------------------------------------------------------------- */ void NeighborhoodBase::onElementsRemoved( const Array<Element> & element_list, const ElementTypeMapArray<UInt> & new_numbering, __attribute__((unused)) const RemovedElementsEvent & event) { AKANTU_DEBUG_IN(); FEEngine & fem = this->model.getFEEngine(); UInt nb_quad = 0; // Change the pairs in new global numbering for (UInt gt = _not_ghost; gt <= _ghost; ++gt) { GhostType ghost_type2 = (GhostType)gt; PairList::iterator first_pair = pair_list[ghost_type2].begin(); PairList::iterator last_pair = pair_list[ghost_type2].end(); for (; first_pair != last_pair; ++first_pair) { IntegrationPoint & q1 = first_pair->first; if (new_numbering.exists(q1.type, q1.ghost_type)) { UInt q1_new_el = new_numbering(q1.type, q1.ghost_type)(q1.element); AKANTU_DEBUG_ASSERT(q1_new_el != UInt(-1), "A local quadrature_point " "as been removed instead of " "just being renumbered"); q1.element = q1_new_el; nb_quad = fem.getNbIntegrationPoints(q1.type, q1.ghost_type); q1.global_num = nb_quad * q1.element + q1.num_point; } IntegrationPoint & q2 = first_pair->second; if (new_numbering.exists(q2.type, q2.ghost_type)) { UInt q2_new_el = new_numbering(q2.type, q2.ghost_type)(q2.element); AKANTU_DEBUG_ASSERT(q2_new_el != UInt(-1), "A local quadrature_point " "as been removed instead of " "just being renumbered"); q2.element = q2_new_el; nb_quad = fem.getNbIntegrationPoints(q2.type, q2.ghost_type); q2.global_num = nb_quad * q2.element + q2.num_point; } } } this->grid_synchronizer->onElementsRemoved(element_list, new_numbering, event); AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu diff --git a/src/model/common/neighborhood_base.hh b/src/model/common/neighborhood_base.hh index dbbaa4a39..7b4546880 100644 --- a/src/model/common/neighborhood_base.hh +++ b/src/model/common/neighborhood_base.hh @@ -1,151 +1,151 @@ /** * @file neighborhood_base.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sat Sep 26 2015 * @date last modification: Wed Nov 25 2015 * * @brief Generic neighborhood of quadrature points * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NEIGHBORHOOD_BASE_HH__ #define __AKANTU_NEIGHBORHOOD_BASE_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "data_accessor.hh" #include "integration_point.hh" #include "synchronizer_registry.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class Model; template <class T> class SpatialGrid; class GridSynchronizer; class RemovedElementsEvent; } // akantu -__BEGIN_AKANTU__ +namespace akantu { class NeighborhoodBase : public Memory, public DataAccessor<Element>, public SynchronizerRegistry { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NeighborhoodBase(Model & model, const ElementTypeMapArray<Real> & quad_coordinates, const ID & id = "neighborhood", const MemoryID & memory_id = 0); virtual ~NeighborhoodBase(); typedef std::vector<std::pair<IntegrationPoint, IntegrationPoint> > PairList; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// intialize the neighborhood virtual void initNeighborhood(); // /// create a synchronizer registry // void createSynchronizerRegistry(DataAccessor * data_accessor); /// initialize the material computed parameter inline void insertQuad(const IntegrationPoint & quad, const Vector<Real> & coords); /// create the pairs of quadrature points void updatePairList(); /// save the pairs of quadrature points in a file void savePairs(const std::string & filename) const; /// save the coordinates of all neighbors of a quad void saveNeighborCoords(const std::string & filename) const; /// create grid synchronizer and exchange ghost cells virtual void createGridSynchronizer() = 0; /// inherited function from MeshEventHandler virtual void onElementsRemoved(const Array<Element> & element_list, const ElementTypeMapArray<UInt> & new_numbering, const RemovedElementsEvent & event); protected: /// create the grid void createGrid(); /* -------------------------------------------------------------------------- */ /* Accessors */ /* -------------------------------------------------------------------------- */ public: AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt); AKANTU_GET_MACRO(Model, model, const Model &); /// return the object handling synchronizers AKANTU_GET_MACRO(PairLists, pair_list, const PairList *); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// the model to which the neighborhood belongs Model & model; /// Radius of impact: to determine if two quadrature points influence each /// other Real neighborhood_radius; /** * the pairs of quadrature points * 0: not ghost to not ghost * 1: not ghost to ghost */ PairList pair_list[2]; /// the regular grid to construct/update the pair lists SpatialGrid<IntegrationPoint> * spatial_grid; bool is_creating_grid; /// the grid synchronizer for parallel computations GridSynchronizer * grid_synchronizer; /// the quadrature point positions const ElementTypeMapArray<Real> & quad_coordinates; /// the spatial dimension of the problem const UInt spatial_dimension; }; -__END_AKANTU__ +} // akantu #include "neighborhood_base_inline_impl.cc" #endif /* __AKANTU_NEIGHBORHOOD_BASE_HH__ */ diff --git a/src/model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc b/src/model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc index 76f66985e..7e7a03bc5 100644 --- a/src/model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc +++ b/src/model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc @@ -1,312 +1,312 @@ /** * @file neighborhood_max_criterion.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * * @date creation: Thu Oct 15 2015 * @date last modification: Tue Nov 24 2015 * * @brief Implementation of class NeighborhoodMaxCriterion * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "neighborhood_max_criterion.hh" #include "grid_synchronizer.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ NeighborhoodMaxCriterion::NeighborhoodMaxCriterion( Model & model, const ElementTypeMapReal & quad_coordinates, const ID & criterion_id, const ID & id, const MemoryID & memory_id) : NeighborhoodBase(model, quad_coordinates, id, memory_id), Parsable(_st_non_local, id), is_highest("is_highest", id, memory_id), criterion(criterion_id, id, memory_id) { AKANTU_DEBUG_IN(); this->registerParam("radius", neighborhood_radius, 100., _pat_parsable | _pat_readable, "Non local radius"); Mesh & mesh = this->model.getMesh(); /// allocate the element type map arrays for _not_ghosts: One entry per quad GhostType ghost_type = _not_ghost; Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type); for (; it != last_type; ++it) { UInt new_size = this->quad_coordinates(*it, ghost_type).getSize(); this->is_highest.alloc(new_size, 1, *it, ghost_type, true); this->criterion.alloc(new_size, 1, *it, ghost_type, true); } /// criterion needs allocation also for ghost ghost_type = _ghost; it = mesh.firstType(spatial_dimension, ghost_type); last_type = mesh.lastType(spatial_dimension, ghost_type); for (; it != last_type; ++it) { UInt new_size = this->quad_coordinates(*it, ghost_type).getSize(); this->criterion.alloc(new_size, 1, *it, ghost_type, true); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ NeighborhoodMaxCriterion::~NeighborhoodMaxCriterion() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void NeighborhoodMaxCriterion::initNeighborhood() { AKANTU_DEBUG_IN(); /// parse the input parameter const Parser & parser = getStaticParser(); const ParserSection & section_neighborhood = *(parser.getSubSections(_st_neighborhood).first); this->parseSection(section_neighborhood); AKANTU_DEBUG_INFO("Creating the grid"); this->createGrid(); /// insert the non-ghost quads into the grid this->insertAllQuads(_not_ghost); /// store the number of current ghost elements for each type in the mesh ElementTypeMap<UInt> nb_ghost_protected; Mesh & mesh = this->model.getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _ghost); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _ghost); for (; it != last_type; ++it) nb_ghost_protected(mesh.getNbElement(*it, _ghost), *it, _ghost); /// create the grid synchronizer this->createGridSynchronizer(); /// insert the ghost quads into the grid this->insertAllQuads(_ghost); /// create the pair lists this->updatePairList(); /// remove the unneccessary ghosts this->cleanupExtraGhostElements(nb_ghost_protected); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void NeighborhoodMaxCriterion::createGridSynchronizer() { this->is_creating_grid = true; std::set<SynchronizationTag> tags; tags.insert(_gst_nh_criterion); std::stringstream sstr; sstr << getID() << ":grid_synchronizer"; this->grid_synchronizer = GridSynchronizer::createGridSynchronizer( this->model.getMesh(), *spatial_grid, sstr.str(), this, tags, 0, false); this->is_creating_grid = false; } /* -------------------------------------------------------------------------- */ void NeighborhoodMaxCriterion::insertAllQuads(const GhostType & ghost_type) { IntegrationPoint q; q.ghost_type = ghost_type; Mesh & mesh = this->model.getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type); for (; it != last_type; ++it) { UInt nb_element = mesh.getNbElement(*it, ghost_type); UInt nb_quad = this->model.getFEEngine().getNbIntegrationPoints(*it, ghost_type); const Array<Real> & quads = this->quad_coordinates(*it, ghost_type); q.type = *it; Array<Real>::const_vector_iterator quad = quads.begin(spatial_dimension); for (UInt e = 0; e < nb_element; ++e) { q.element = e; for (UInt nq = 0; nq < nb_quad; ++nq) { q.num_point = nq; q.global_num = q.element * nb_quad + nq; spatial_grid->insert(q, *quad); ++quad; } } } } /* -------------------------------------------------------------------------- */ void NeighborhoodMaxCriterion::findMaxQuads( std::vector<IntegrationPoint> & max_quads) { AKANTU_DEBUG_IN(); /// clear the element type maps this->is_highest.clear(); this->criterion.clear(); /// update the values of the criterion this->model.updateDataForNonLocalCriterion(criterion); /// start the exchange the value of the criterion on the ghost elements this->model.asynchronousSynchronize(_gst_nh_criterion); /// compare to not-ghost neighbors checkNeighbors(_not_ghost); /// finish the exchange this->model.waitEndSynchronize(_gst_nh_criterion); /// compare to ghost neighbors checkNeighbors(_ghost); /// extract the quads with highest criterion in their neighborhood IntegrationPoint quad; quad.ghost_type = _not_ghost; Mesh & mesh = this->model.getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _not_ghost); for (; it != last_type; ++it) { quad.type = *it; Array<bool>::const_scalar_iterator is_highest_it = is_highest(*it, _not_ghost).begin(); Array<bool>::const_scalar_iterator is_highest_end = is_highest(*it, _not_ghost).end(); UInt nb_quadrature_points = this->model.getFEEngine().getNbIntegrationPoints(*it, _not_ghost); UInt q = 0; /// loop over is_highest for the current element type for (; is_highest_it != is_highest_end; ++is_highest_it, ++q) { if (*is_highest_it) { /// gauss point has the highest stress in his neighbourhood quad.element = q / nb_quadrature_points; quad.global_num = q; quad.num_point = q % nb_quadrature_points; max_quads.push_back(quad); } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void NeighborhoodMaxCriterion::checkNeighbors(const GhostType & ghost_type2) { AKANTU_DEBUG_IN(); PairList::const_iterator first_pair = pair_list[ghost_type2].begin(); PairList::const_iterator last_pair = pair_list[ghost_type2].end(); // Compute the weights for (; first_pair != last_pair; ++first_pair) { const IntegrationPoint & lq1 = first_pair->first; const IntegrationPoint & lq2 = first_pair->second; Array<bool> & has_highest_eq_stress_1 = is_highest(lq1.type, lq1.ghost_type); const Array<Real> & criterion_1 = this->criterion(lq1.type, lq1.ghost_type); const Array<Real> & criterion_2 = this->criterion(lq2.type, lq2.ghost_type); if (criterion_1(lq1.global_num) < criterion_2(lq2.global_num)) has_highest_eq_stress_1(lq1.global_num) = false; else if (ghost_type2 != _ghost) { Array<bool> & has_highest_eq_stress_2 = is_highest(lq2.type, lq2.ghost_type); has_highest_eq_stress_2(lq2.global_num) = false; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void NeighborhoodMaxCriterion::cleanupExtraGhostElements( const ElementTypeMap<UInt> & nb_ghost_protected) { Mesh & mesh = this->model.getMesh(); /// create remove elements event RemovedElementsEvent remove_elem(mesh); /// create set of ghosts to keep std::set<Element> relevant_ghost_elements; PairList::const_iterator first_pair = pair_list[_ghost].begin(); PairList::const_iterator last_pair = pair_list[_ghost].end(); for (; first_pair != last_pair; ++first_pair) { const IntegrationPoint & q2 = first_pair->second; relevant_ghost_elements.insert(q2); } Array<Element> ghosts_to_erase(0); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _ghost); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _ghost); Element element; element.ghost_type = _ghost; std::set<Element>::const_iterator end = relevant_ghost_elements.end(); for (; it != last_type; ++it) { element.type = *it; UInt nb_ghost_elem = mesh.getNbElement(*it, _ghost); UInt nb_ghost_elem_protected = 0; try { nb_ghost_elem_protected = nb_ghost_protected(*it, _ghost); } catch (...) { } if (!remove_elem.getNewNumbering().exists(*it, _ghost)) remove_elem.getNewNumbering().alloc(nb_ghost_elem, 1, *it, _ghost); else remove_elem.getNewNumbering(*it, _ghost).resize(nb_ghost_elem); Array<UInt> & new_numbering = remove_elem.getNewNumbering(*it, _ghost); for (UInt g = 0; g < nb_ghost_elem; ++g) { element.element = g; if (element.element >= nb_ghost_elem_protected && relevant_ghost_elements.find(element) == end) { ghosts_to_erase.push_back(element); new_numbering(element.element) = UInt(-1); } } /// renumber remaining ghosts UInt ng = 0; for (UInt g = 0; g < nb_ghost_elem; ++g) { if (new_numbering(g) != UInt(-1)) { new_numbering(g) = ng; ++ng; } } } mesh.sendEvent(remove_elem); this->onElementsRemoved(ghosts_to_erase, remove_elem.getNewNumbering(), remove_elem); } -__END_AKANTU__ +} // akantu diff --git a/src/model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion.hh b/src/model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion.hh index 59744a10f..3ea9e3e94 100644 --- a/src/model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion.hh +++ b/src/model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion.hh @@ -1,117 +1,117 @@ /** * @file neighborhood_max_criterion.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * * @date creation: Sat Sep 26 2015 * @date last modification: Thu Oct 15 2015 * * @brief Neighborhood to find a maximum value in a neighborhood * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NEIGHBORHOOD_MAX_CRITERION_BASE_HH__ #define __AKANTU_NEIGHBORHOOD_MAX_CRITERION_BASE_HH__ /* -------------------------------------------------------------------------- */ #include "neighborhood_base.hh" #include "parsable.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class NeighborhoodMaxCriterion : public NeighborhoodBase, public Parsable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NeighborhoodMaxCriterion(Model & model, const ElementTypeMapReal & quad_coordinates, const ID & criterion_id, const ID & id = "neighborhood_max_criterion", const MemoryID & memory_id = 0); virtual ~NeighborhoodMaxCriterion(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the neighborhood virtual void initNeighborhood(); /// create grid synchronizer and exchange ghost cells virtual void createGridSynchronizer(); /// find the quads which have the maximum criterion in their neighborhood void findMaxQuads(std::vector<IntegrationPoint> & max_quads); protected: /// remove unneccessary ghost elements void cleanupExtraGhostElements(const ElementTypeMap<UInt> & nb_ghost_protected); /// insert the quadrature points in the grid void insertAllQuads(const GhostType & ghost_type); /// compare criterion with neighbors void checkNeighbors(const GhostType & ghost_type); /* -------------------------------------------------------------------------- */ /* DataAccessor inherited members */ /* -------------------------------------------------------------------------- */ public: virtual inline UInt getNbDataForElements(const Array<Element> & elements, SynchronizationTag tag) const; virtual inline void packElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag) const; virtual inline void unpackElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag); /* -------------------------------------------------------------------------- */ /* Accessors */ /* -------------------------------------------------------------------------- */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// a boolean to store the information if a quad has the max /// criterion in the neighborhood ElementTypeMapArray<bool> is_highest; /// an element type map to store the flattened internal of the criterion ElementTypeMapReal criterion; }; -__END_AKANTU__ +} // akantu #include "neighborhood_max_criterion_inline_impl.cc" #endif /* __AKANTU_NEIGHBORHOOD_MAX_CRITERION_BASE_HH__ */ diff --git a/src/model/common/non_local_toolbox/non_local_manager.cc b/src/model/common/non_local_toolbox/non_local_manager.cc index 966e80009..763ff7843 100644 --- a/src/model/common/non_local_toolbox/non_local_manager.cc +++ b/src/model/common/non_local_toolbox/non_local_manager.cc @@ -1,700 +1,700 @@ /** * @file non_local_manager.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Apr 13 2012 * @date last modification: Wed Dec 16 2015 * * @brief Implementation of non-local manager * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "non_local_manager.hh" #include "base_weight_function.hh" #include "material_non_local.hh" #include "non_local_neighborhood.hh" /* -------------------------------------------------------------------------- */ #include <numeric> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ NonLocalManager::NonLocalManager(SolidMechanicsModel & model, const ID & id, const MemoryID & memory_id) : Memory(id, memory_id), Parsable(_st_neighborhoods, id), model(model), quad_positions("quad_positions", id, memory_id), volumes("volumes", id, memory_id), spatial_dimension(this->model.getSpatialDimension()), compute_stress_calls(0), dummy_registry(NULL), dummy_grid(NULL) { Mesh & mesh = this->model.getMesh(); mesh.registerEventHandler(*this); /// initialize the element type map array /// it will be resized to nb_quad * nb_element during the computation of /// coords mesh.initElementTypeMapArray(quad_positions, spatial_dimension, spatial_dimension, false, _ek_regular, true); this->initElementTypeMap(1, volumes, this->model.getFEEngine()); /// parse the neighborhood information from the input file const Parser & parser = getStaticParser(); /// iterate over all the non-local sections and store them in a map std::pair<Parser::const_section_iterator, Parser::const_section_iterator> weight_sect = parser.getSubSections(_st_non_local); Parser::const_section_iterator it = weight_sect.first; for (; it != weight_sect.second; ++it) { const ParserSection & section = *it; ID name = section.getName(); this->weight_function_types[name] = section; } this->dummy_registry = new SynchronizerRegistry(this->dummy_accessor); } /* -------------------------------------------------------------------------- */ NonLocalManager::~NonLocalManager() { /// delete neighborhoods NeighborhoodMap::iterator it; for (it = neighborhoods.begin(); it != neighborhoods.end(); ++it) { if (it->second) delete it->second; } /// delete non-local variables std::map<ID, NonLocalVariable *>::iterator it_variables; for (it_variables = non_local_variables.begin(); it_variables != non_local_variables.end(); ++it_variables) { if (it_variables->second) delete it_variables->second; } std::map<ID, ElementTypeMapReal *>::iterator it_internals; for (it_internals = weight_function_internals.begin(); it_internals != weight_function_internals.end(); ++it_internals) { if (it_internals->second) delete it_internals->second; } std::map<ID, GridSynchronizer *>::iterator grid_synch_it; for (grid_synch_it = dummy_synchronizers.begin(); grid_synch_it != dummy_synchronizers.end(); ++grid_synch_it) { if (grid_synch_it->second) delete grid_synch_it->second; } /// delete all objects related to the dummy synchronizers delete dummy_registry; delete dummy_grid; } /* -------------------------------------------------------------------------- */ void NonLocalManager::setJacobians(const FEEngine & fe_engine, const ElementKind & kind) { Mesh & mesh = this->model.getMesh(); for (UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType)g; Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt, kind); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, gt, kind); for (; it != last_type; ++it) { jacobians(*it, gt) = &fe_engine.getIntegratorInterface().getJacobians(*it, gt); } } } /* -------------------------------------------------------------------------- */ void NonLocalManager::createNeighborhood(const ID & weight_func, const ID & neighborhood_id) { AKANTU_DEBUG_IN(); const ParserSection & section = this->weight_function_types[weight_func]; const ID weight_func_type = section.getOption(); /// create new neighborhood for given ID std::stringstream sstr; sstr << id << ":neighborhood:" << neighborhood_id; if (weight_func_type == "base_wf") neighborhoods[neighborhood_id] = new NonLocalNeighborhood<BaseWeightFunction>( *this, this->quad_positions, sstr.str()); else if (weight_func_type == "remove_wf") neighborhoods[neighborhood_id] = new NonLocalNeighborhood<RemoveDamagedWeightFunction>( *this, this->quad_positions, sstr.str()); else if (weight_func_type == "stress_wf") neighborhoods[neighborhood_id] = new NonLocalNeighborhood<StressBasedWeightFunction>( *this, this->quad_positions, sstr.str()); else if (weight_func_type == "damage_wf") neighborhoods[neighborhood_id] = new NonLocalNeighborhood<DamagedWeightFunction>( *this, this->quad_positions, sstr.str()); else AKANTU_EXCEPTION("error in weight function type provided in material file"); neighborhoods[neighborhood_id]->parseSection(section); neighborhoods[neighborhood_id]->initNeighborhood(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void NonLocalManager::createNeighborhoodSynchronizers() { /// exchange all the neighborhood IDs, so that every proc knows how many /// neighborhoods exist globally /// First: Compute locally the maximum ID size UInt max_id_size = 0; UInt current_size = 0; NeighborhoodMap::const_iterator it; for (it = neighborhoods.begin(); it != neighborhoods.end(); ++it) { current_size = it->first.size(); if (current_size > max_id_size) max_id_size = current_size; } /// get the global maximum ID size on each proc StaticCommunicator & static_communicator = akantu::StaticCommunicator::getStaticCommunicator(); static_communicator.allReduce(&max_id_size, 1, _so_max); /// get the rank for this proc and the total nb proc UInt prank = static_communicator.whoAmI(); UInt psize = static_communicator.getNbProc(); /// exchange the number of neighborhoods on each proc Array<Int> nb_neighborhoods_per_proc(psize); nb_neighborhoods_per_proc(prank) = neighborhoods.size(); static_communicator.allGather(nb_neighborhoods_per_proc.storage(), 1); /// compute the total number of neighborhoods UInt nb_neighborhoods_global = std::accumulate( nb_neighborhoods_per_proc.begin(), nb_neighborhoods_per_proc.end(), 0); /// allocate an array of chars to store the names of all neighborhoods Array<char> buffer(nb_neighborhoods_global, max_id_size); /// starting index on this proc UInt starting_index = std::accumulate(nb_neighborhoods_per_proc.begin(), nb_neighborhoods_per_proc.begin() + prank, 0); it = neighborhoods.begin(); /// store the names of local neighborhoods in the buffer for (UInt i = 0; i < neighborhoods.size(); ++i, ++it) { UInt c = 0; for (; c < it->first.size(); ++c) buffer(i + starting_index, c) = it->first[c]; for (; c < max_id_size; ++c) buffer(i + starting_index, c) = char(0); } /// store the nb of data to send in the all gather Array<Int> buffer_size(nb_neighborhoods_per_proc); buffer_size *= max_id_size; /// exchange the names of all the neighborhoods with all procs static_communicator.allGatherV(buffer.storage(), buffer_size.storage()); for (UInt i = 0; i < nb_neighborhoods_global; ++i) { std::stringstream neighborhood_id; for (UInt c = 0; c < max_id_size; ++c) { if (buffer(i, c) == char(0)) break; neighborhood_id << buffer(i, c); } global_neighborhoods.insert(neighborhood_id.str()); } /// this proc does not know all the neighborhoods -> create dummy /// grid so that this proc can participate in the all gather for /// detecting the overlap of neighborhoods this proc doesn't know Vector<Real> grid_center(this->spatial_dimension); for (UInt s = 0; s < this->spatial_dimension; ++s) grid_center(s) = std::numeric_limits<Real>::max(); dummy_grid = new SpatialGrid<IntegrationPoint>(spatial_dimension, 0., grid_center); std::set<SynchronizationTag> tags; tags.insert(_gst_mnl_for_average); tags.insert(_gst_mnl_weight); std::set<ID>::const_iterator global_neighborhoods_it = global_neighborhoods.begin(); for (; global_neighborhoods_it != global_neighborhoods.end(); ++global_neighborhoods_it) { it = neighborhoods.find(*global_neighborhoods_it); if (it != neighborhoods.end()) { it->second->createGridSynchronizer(); } else { ID neighborhood_name = *global_neighborhoods_it; std::stringstream sstr; sstr << getID() << ":" << neighborhood_name << ":grid_synchronizer"; dummy_synchronizers[neighborhood_name] = GridSynchronizer::createGridSynchronizer( this->model.getMesh(), *dummy_grid, sstr.str(), dummy_registry, tags, 0, false); } } } /* -------------------------------------------------------------------------- */ void NonLocalManager::flattenInternal(ElementTypeMapReal & internal_flat, const GhostType & ghost_type, const ElementKind & kind) { const ID field_name = internal_flat.getName(); for (UInt m = 0; m < this->non_local_materials.size(); ++m) { Material & material = *(this->non_local_materials[m]); if (material.isInternal<Real>(field_name, kind)) material.flattenInternal(field_name, internal_flat, ghost_type, kind); } } /* -------------------------------------------------------------------------- */ void NonLocalManager::averageInternals(const GhostType & ghost_type) { /// update the weights of the weight function if (ghost_type == _not_ghost) this->computeWeights(); /// loop over all neighborhoods and compute the non-local variables NeighborhoodMap::iterator neighborhood_it = neighborhoods.begin(); NeighborhoodMap::iterator neighborhood_end = neighborhoods.end(); for (; neighborhood_it != neighborhood_end; ++neighborhood_it) { /// loop over all the non-local variables of the given neighborhood std::map<ID, NonLocalVariable *>::iterator non_local_variable_it = non_local_variables.begin(); std::map<ID, NonLocalVariable *>::iterator non_local_variable_end = non_local_variables.end(); for (; non_local_variable_it != non_local_variable_end; ++non_local_variable_it) { NonLocalVariable * non_local_var = non_local_variable_it->second; neighborhood_it->second->weightedAverageOnNeighbours( non_local_var->local, non_local_var->non_local, non_local_var->nb_component, ghost_type); } } } /* -------------------------------------------------------------------------- */ void NonLocalManager::init() { /// store the number of current ghost elements for each type in the mesh ElementTypeMap<UInt> nb_ghost_protected; Mesh & mesh = this->model.getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _ghost); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _ghost); for (; it != last_type; ++it) nb_ghost_protected(mesh.getNbElement(*it, _ghost), *it, _ghost); /// exchange the missing ghosts for the non-local neighborhoods this->createNeighborhoodSynchronizers(); /// insert the ghost quadrature points of the non-local materials into the /// non-local neighborhoods for (UInt m = 0; m < this->non_local_materials.size(); ++m) { switch (spatial_dimension) { case 1: dynamic_cast<MaterialNonLocal<1> &>(*(this->non_local_materials[m])) .insertQuadsInNeighborhoods(_ghost); break; case 2: dynamic_cast<MaterialNonLocal<2> &>(*(this->non_local_materials[m])) .insertQuadsInNeighborhoods(_ghost); break; case 3: dynamic_cast<MaterialNonLocal<3> &>(*(this->non_local_materials[m])) .insertQuadsInNeighborhoods(_ghost); break; } } FEEngine & fee = this->model.getFEEngine(); this->updatePairLists(); /// cleanup the unneccessary ghost elements this->cleanupExtraGhostElements(nb_ghost_protected); this->setJacobians(fee, _ek_regular); this->initNonLocalVariables(); this->computeWeights(); } /* -------------------------------------------------------------------------- */ void NonLocalManager::initNonLocalVariables() { /// loop over all the non-local variables std::map<ID, NonLocalVariable *>::iterator non_local_variable_it = non_local_variables.begin(); std::map<ID, NonLocalVariable *>::iterator non_local_variable_end = non_local_variables.end(); for (; non_local_variable_it != non_local_variable_end; ++non_local_variable_it) { NonLocalVariable & variable = *(non_local_variable_it->second); this->initElementTypeMap(variable.nb_component, variable.non_local, this->model.getFEEngine()); } } /* -------------------------------------------------------------------------- */ void NonLocalManager::initElementTypeMap(UInt nb_component, ElementTypeMapReal & element_map, const FEEngine & fee, const ElementKind el_kind) { Mesh & mesh = this->model.getMesh(); /// need to resize the arrays for (UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType)g; Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt, el_kind); Mesh::type_iterator end = mesh.lastType(spatial_dimension, gt, el_kind); for (; it != end; ++it) { ElementType el_type = *it; UInt nb_element = mesh.getNbElement(*it, gt); UInt nb_quads = fee.getNbIntegrationPoints(*it, gt); if (!element_map.exists(el_type, gt)) { element_map.alloc(nb_element * nb_quads, nb_component, el_type, gt); } } } } /* -------------------------------------------------------------------------- */ void NonLocalManager::distributeInternals(ElementKind kind) { /// loop over all the non-local variables and copy back their values into the /// materials std::map<ID, NonLocalVariable *>::iterator non_local_variable_it = non_local_variables.begin(); std::map<ID, NonLocalVariable *>::iterator non_local_variable_end = non_local_variables.end(); for (; non_local_variable_it != non_local_variable_end; ++non_local_variable_it) { NonLocalVariable * non_local_var = non_local_variable_it->second; const ID field_name = non_local_var->non_local.getName(); /// loop over all the materials for (UInt m = 0; m < this->non_local_materials.size(); ++m) { if (this->non_local_materials[m]->isInternal<Real>(field_name, kind)) switch (spatial_dimension) { case 1: dynamic_cast<MaterialNonLocal<1> &>(*(this->non_local_materials[m])) .updateNonLocalInternals(non_local_var->non_local, field_name, non_local_var->nb_component); break; case 2: dynamic_cast<MaterialNonLocal<2> &>(*(this->non_local_materials[m])) .updateNonLocalInternals(non_local_var->non_local, field_name, non_local_var->nb_component); break; case 3: dynamic_cast<MaterialNonLocal<3> &>(*(this->non_local_materials[m])) .updateNonLocalInternals(non_local_var->non_local, field_name, non_local_var->nb_component); break; } } } } /* -------------------------------------------------------------------------- */ void NonLocalManager::computeAllNonLocalStresses() { /// update the flattened version of the internals std::map<ID, NonLocalVariable *>::iterator non_local_variable_it = non_local_variables.begin(); std::map<ID, NonLocalVariable *>::iterator non_local_variable_end = non_local_variables.end(); for (; non_local_variable_it != non_local_variable_end; ++non_local_variable_it) { non_local_variable_it->second->local.clear(); non_local_variable_it->second->non_local.clear(); for (UInt gt = _not_ghost; gt <= _ghost; ++gt) { GhostType ghost_type = (GhostType)gt; this->flattenInternal(non_local_variable_it->second->local, ghost_type, _ek_regular); } } this->volumes.clear(); /// loop over all the neighborhoods and compute intiate the /// exchange of the non-local_variables // std::set<ID>::const_iterator global_neighborhood_it = // global_neighborhoods.begin(); // NeighborhoodMap::iterator it; // for(; global_neighborhood_it != global_neighborhoods.end(); // ++global_neighborhood_it) { // it = neighborhoods.find(*global_neighborhood_it); // if (it != neighborhoods.end()) // it->second->getSynchronizerRegistry().asynchronousSynchronize(_gst_mnl_for_average); // else // dummy_synchronizers[*global_neighborhood_it]->asynchronousSynchronize(dummy_accessor, // _gst_mnl_for_average); // } NeighborhoodMap::iterator neighborhood_it = neighborhoods.begin(); // NeighborhoodMap::iterator neighborhood_end = neighborhoods.end(); for (; neighborhood_it != neighborhoods.end(); ++neighborhood_it) { neighborhood_it->second->getSynchronizerRegistry().asynchronousSynchronize( _gst_mnl_for_average); } this->averageInternals(_not_ghost); AKANTU_DEBUG_INFO("Wait distant non local stresses"); /// loop over all the neighborhoods and block until all non-local /// variables have been exchanged // global_neighborhood_it = global_neighborhoods.begin(); // for(; global_neighborhood_it != global_neighborhoods.end(); // ++global_neighborhood_it) { // it = neighborhoods.find(*global_neighborhood_it); // if (it != neighborhoods.end()) // it->second->getSynchronizerRegistry().waitEndSynchronize(_gst_mnl_for_average); // else // dummy_synchronizers[*global_neighborhood_it]->waitEndSynchronize(dummy_accessor, // _gst_mnl_for_average); // } neighborhood_it = neighborhoods.begin(); for (; neighborhood_it != neighborhoods.end(); ++neighborhood_it) { neighborhood_it->second->getSynchronizerRegistry().waitEndSynchronize( _gst_mnl_for_average); } this->averageInternals(_ghost); /// copy the results in the materials this->distributeInternals(_ek_regular); /// loop over all the materials and update the weights for (UInt m = 0; m < this->non_local_materials.size(); ++m) { switch (spatial_dimension) { case 1: dynamic_cast<MaterialNonLocal<1> &>(*(this->non_local_materials[m])) .computeNonLocalStresses(_not_ghost); break; case 2: dynamic_cast<MaterialNonLocal<2> &>(*(this->non_local_materials[m])) .computeNonLocalStresses(_not_ghost); break; case 3: dynamic_cast<MaterialNonLocal<3> &>(*(this->non_local_materials[m])) .computeNonLocalStresses(_not_ghost); break; } } ++this->compute_stress_calls; } /* -------------------------------------------------------------------------- */ void NonLocalManager::cleanupExtraGhostElements( ElementTypeMap<UInt> & nb_ghost_protected) { typedef std::set<Element> ElementSet; ElementSet relevant_ghost_elements; ElementSet to_keep_per_neighborhood; /// loop over all the neighborhoods and get their protected ghosts NeighborhoodMap::iterator neighborhood_it = neighborhoods.begin(); NeighborhoodMap::iterator neighborhood_end = neighborhoods.end(); for (; neighborhood_it != neighborhood_end; ++neighborhood_it) { neighborhood_it->second->cleanupExtraGhostElements( to_keep_per_neighborhood); ElementSet::const_iterator it = to_keep_per_neighborhood.begin(); for (; it != to_keep_per_neighborhood.end(); ++it) relevant_ghost_elements.insert(*it); to_keep_per_neighborhood.clear(); } /// remove all unneccessary ghosts from the mesh /// Create list of element to remove and new numbering for element to keep Mesh & mesh = this->model.getMesh(); ElementSet ghost_to_erase; Mesh::type_iterator it = mesh.firstType(spatial_dimension, _ghost); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _ghost); RemovedElementsEvent remove_elem(mesh); Element element; element.ghost_type = _ghost; for (; it != last_type; ++it) { element.type = *it; UInt nb_ghost_elem = mesh.getNbElement(*it, _ghost); UInt nb_ghost_elem_protected = 0; try { nb_ghost_elem_protected = nb_ghost_protected(*it, _ghost); } catch (...) { } if (!remove_elem.getNewNumbering().exists(*it, _ghost)) remove_elem.getNewNumbering().alloc(nb_ghost_elem, 1, *it, _ghost); else remove_elem.getNewNumbering(*it, _ghost).resize(nb_ghost_elem); Array<UInt> & new_numbering = remove_elem.getNewNumbering(*it, _ghost); for (UInt g = 0; g < nb_ghost_elem; ++g) { element.element = g; if (element.element >= nb_ghost_elem_protected && relevant_ghost_elements.find(element) == relevant_ghost_elements.end()) { remove_elem.getList().push_back(element); new_numbering(element.element) = UInt(-1); } } /// renumber remaining ghosts UInt ng = 0; for (UInt g = 0; g < nb_ghost_elem; ++g) { if (new_numbering(g) != UInt(-1)) { new_numbering(g) = ng; ++ng; } } } it = mesh.firstType(spatial_dimension, _not_ghost); last_type = mesh.lastType(spatial_dimension, _not_ghost); for (; it != last_type; ++it) { UInt nb_elem = mesh.getNbElement(*it, _not_ghost); if (!remove_elem.getNewNumbering().exists(*it, _not_ghost)) remove_elem.getNewNumbering().alloc(nb_elem, 1, *it, _not_ghost); Array<UInt> & new_numbering = remove_elem.getNewNumbering(*it, _not_ghost); for (UInt e = 0; e < nb_elem; ++e) { new_numbering(e) = e; } } mesh.sendEvent(remove_elem); } /* -------------------------------------------------------------------------- */ void NonLocalManager::onElementsRemoved( const Array<Element> & element_list, const ElementTypeMapArray<UInt> & new_numbering, __attribute__((unused)) const RemovedElementsEvent & event) { FEEngine & fee = this->model.getFEEngine(); this->removeIntegrationPointsFromMap(event.getNewNumbering(), spatial_dimension, quad_positions, fee, _ek_regular); this->removeIntegrationPointsFromMap(event.getNewNumbering(), 1, volumes, fee, _ek_regular); /// loop over all the neighborhoods and call onElementsRemoved std::set<ID>::const_iterator global_neighborhood_it = global_neighborhoods.begin(); NeighborhoodMap::iterator it; for (; global_neighborhood_it != global_neighborhoods.end(); ++global_neighborhood_it) { it = neighborhoods.find(*global_neighborhood_it); if (it != neighborhoods.end()) it->second->onElementsRemoved(element_list, new_numbering, event); else dummy_synchronizers[*global_neighborhood_it]->onElementsRemoved( element_list, new_numbering, event); } } /* -------------------------------------------------------------------------- */ void NonLocalManager::onElementsAdded(__attribute__((unused)) const Array<Element> & element_list, __attribute__((unused)) const NewElementsEvent & event) { this->resizeElementTypeMap(1, volumes, model.getFEEngine()); this->resizeElementTypeMap(spatial_dimension, quad_positions, model.getFEEngine()); } /* -------------------------------------------------------------------------- */ void NonLocalManager::resizeElementTypeMap(UInt nb_component, ElementTypeMapReal & element_map, const FEEngine & fee, const ElementKind el_kind) { Mesh & mesh = this->model.getMesh(); for (UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType)g; Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt, el_kind); Mesh::type_iterator end = mesh.lastType(spatial_dimension, gt, el_kind); for (; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it, gt); UInt nb_quads = fee.getNbIntegrationPoints(*it, gt); if (!element_map.exists(*it, gt)) element_map.alloc(nb_element * nb_quads, nb_component, *it, gt); else element_map(*it, gt).resize(nb_element * nb_quads); } } } /* -------------------------------------------------------------------------- */ void NonLocalManager::removeIntegrationPointsFromMap( const ElementTypeMapArray<UInt> & new_numbering, UInt nb_component, ElementTypeMapReal & element_map, const FEEngine & fee, const ElementKind el_kind) { for (UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType)g; ElementTypeMapArray<UInt>::type_iterator it = new_numbering.firstType(_all_dimensions, gt, el_kind); ElementTypeMapArray<UInt>::type_iterator end = new_numbering.lastType(_all_dimensions, gt, el_kind); for (; it != end; ++it) { ElementType type = *it; if (element_map.exists(type, gt)) { const Array<UInt> & renumbering = new_numbering(type, gt); Array<Real> & vect = element_map(type, gt); UInt nb_quad_per_elem = fee.getNbIntegrationPoints(type, gt); Array<Real> tmp(renumbering.getSize() * nb_quad_per_elem, nb_component); AKANTU_DEBUG_ASSERT( tmp.getSize() == vect.getSize(), "Something strange append some mater was created from nowhere!!"); AKANTU_DEBUG_ASSERT( tmp.getSize() == vect.getSize(), "Something strange append some mater was created or disappeared in " << vect.getID() << "(" << vect.getSize() << "!=" << tmp.getSize() << ") " "!!"); UInt new_size = 0; for (UInt i = 0; i < renumbering.getSize(); ++i) { UInt new_i = renumbering(i); if (new_i != UInt(-1)) { memcpy(tmp.storage() + new_i * nb_component * nb_quad_per_elem, vect.storage() + i * nb_component * nb_quad_per_elem, nb_component * nb_quad_per_elem * sizeof(Real)); ++new_size; } } tmp.resize(new_size * nb_quad_per_elem); vect.copy(tmp); } } } } -__END_AKANTU__ +} // akantu diff --git a/src/model/common/non_local_toolbox/non_local_manager.hh b/src/model/common/non_local_toolbox/non_local_manager.hh index 299b6204b..e86c19905 100644 --- a/src/model/common/non_local_toolbox/non_local_manager.hh +++ b/src/model/common/non_local_toolbox/non_local_manager.hh @@ -1,289 +1,289 @@ /** * @file non_local_manager.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Dec 08 2015 * * @brief Classes that manages all the non-local neighborhoods * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NON_LOCAL_MANAGER_HH__ #define __AKANTU_NON_LOCAL_MANAGER_HH__ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" #include "solid_mechanics_model.hh" #include "non_local_neighborhood_base.hh" #include "mesh_events.hh" #include "parsable.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class NonLocalManager : public Memory, public Parsable, public MeshEventHandler { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NonLocalManager(SolidMechanicsModel & model, const ID & id, const MemoryID & memory_id); virtual ~NonLocalManager(); typedef std::map<ID, NonLocalNeighborhoodBase *> NeighborhoodMap; typedef std::pair<ID, ID> KeyCOO; /* ------------------------------------------------------------------------ */ /* Methods */ /* ----------------------------------------------------------------------- */ public: /// initialize the non-local manager: compute pair lists and weights for all /// neighborhoods virtual void init(); /// insert new quadrature point in the grid inline void insertQuad(const IntegrationPoint & quad, const Vector<Real> & coords, const ID & neighborhood); /// register non-local neighborhood inline void registerNeighborhood(const ID & neighborhood, const ID & weight_func_id); /// associate a non-local variable to a neighborhood void nonLocalVariableToNeighborhood(const ID & id, const ID & neighborhood); /// return the fem object associated with a provided name inline NonLocalNeighborhoodBase & getNeighborhood(const ID & name) const; /// create the grid synchronizers for each neighborhood void createNeighborhoodSynchronizers(); /// compute the weights in each neighborhood for non-local averaging inline void computeWeights(); /// compute the weights in each neighborhood for non-local averaging inline void updatePairLists(); /// register a new non-local material inline void registerNonLocalMaterial(Material & new_mat); /// register a non-local variable inline void registerNonLocalVariable(const ID & variable_name, const ID & nl_variable_name, UInt nb_component); /// average the non-local variables void averageInternals(const GhostType & ghost_type = _not_ghost); /// average the internals and compute the non-local stresses virtual void computeAllNonLocalStresses(); /// register a new internal needed for the weight computations inline ElementTypeMapReal & registerWeightFunctionInternal(const ID & field_name); /// update the flattened version of the weight function internals inline void updateWeightFunctionInternals(); /// get Nb data for synchronization in parallel inline UInt getNbDataForElements(const Array<Element> & elements, const ID & id) const; /// pack data for synchronization in parallel inline void packElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag, const ID & id) const; /// unpack data for synchronization in parallel inline void unpackElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag, const ID & id) const; protected: /// create a new neighborhood for a given domain ID void createNeighborhood(const ID & weight_func, const ID & neighborhood); /// flatten the material internal fields needed for the non-local computations void flattenInternal(ElementTypeMapReal & internal_flat, const GhostType & ghost_type, const ElementKind & kind); /// set the values of the jacobians void setJacobians(const FEEngine & fe_engine, const ElementKind & kind); /// allocation of eelment type maps void initElementTypeMap(UInt nb_component, ElementTypeMapReal & element_map, const FEEngine & fe_engine, const ElementKind el_kind = _ek_regular); /// resizing of element type maps void resizeElementTypeMap(UInt nb_component, ElementTypeMapReal & element_map, const FEEngine & fee, const ElementKind el_kind = _ek_regular); /// remove integration points from element type maps void removeIntegrationPointsFromMap( const ElementTypeMapArray<UInt> & new_numbering, UInt nb_component, ElementTypeMapReal & element_map, const FEEngine & fee, const ElementKind el_kind = _ek_regular); /// allocate the non-local variables void initNonLocalVariables(); /// copy the results of the averaging in the materials void distributeInternals(ElementKind kind); /// cleanup unneccessary ghosts void cleanupExtraGhostElements(ElementTypeMap<UInt> & nb_ghost_protected); /* ------------------------------------------------------------------------ */ /* MeshEventHandler inherited members */ /* ------------------------------------------------------------------------ */ public: virtual void onElementsRemoved(const Array<Element> & element_list, const ElementTypeMapArray<UInt> & new_numbering, const RemovedElementsEvent & event); virtual void onElementsAdded(const Array<Element> & element_list, const NewElementsEvent & event); virtual void onElementsChanged(__attribute__((unused)) const Array<Element> & old_elements_list, __attribute__((unused)) const Array<Element> & new_elements_list, __attribute__((unused)) const ElementTypeMapArray<UInt> & new_numbering, __attribute__((unused)) const ChangedElementsEvent & event) {}; virtual void onNodesAdded(__attribute__((unused)) const Array<UInt> & nodes_list, __attribute__((unused)) const NewNodesEvent & event) {}; virtual void onNodesRemoved(__attribute__((unused)) const Array<UInt> & nodes_list, __attribute__((unused)) const Array<UInt> & new_numbering, __attribute__((unused)) const RemovedNodesEvent & event) {}; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt); AKANTU_GET_MACRO(Model, model, const SolidMechanicsModel &); AKANTU_GET_MACRO_NOT_CONST(Volumes, volumes, ElementTypeMapReal &) AKANTU_GET_MACRO(NbStressCalls, compute_stress_calls, UInt); inline const Array<Real> & getJacobians(const ElementType & type, const GhostType & ghost_type) { return *jacobians(type, ghost_type); } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// the non-local neighborhoods present NeighborhoodMap neighborhoods; /// list of all the non-local materials in the model std::vector<Material *> non_local_materials; struct NonLocalVariable { NonLocalVariable(const ID & variable_name, const ID & nl_variable_name, const ID & id, UInt nb_component) : local(variable_name, id, 0), non_local(nl_variable_name, id, 0), nb_component(nb_component) {} ElementTypeMapReal local; ElementTypeMapReal non_local; UInt nb_component; }; /// the non-local variables associated to a certain neighborhood std::map<ID, NonLocalVariable *> non_local_variables; /// reference to the model SolidMechanicsModel & model; /// jacobians for all the elements in the mesh ElementTypeMap<const Array<Real> *> jacobians; /// store the position of the quadrature points ElementTypeMapReal quad_positions; /// store the volume of each quadrature point for the non-local weight /// normalization ElementTypeMapReal volumes; /// the spatial dimension const UInt spatial_dimension; /// counter for computeStress calls UInt compute_stress_calls; /// map to store weight function types from input file std::map<ID, ParserSection> weight_function_types; /// map to store the internals needed by the weight functions std::map<ID, ElementTypeMapReal *> weight_function_internals; /* -------------------------------------------------------------------------- */ /// the following are members needed to make this processor participate in the /// grid creation of neighborhoods he doesn't own as a member. For details see /// createGridSynchronizers function /// synchronizer registry for dummy grid synchronizers SynchronizerRegistry * dummy_registry; /// map of dummy synchronizers std::map<ID, GridSynchronizer *> dummy_synchronizers; /// dummy spatial grid SpatialGrid<IntegrationPoint> * dummy_grid; /// create a set of all neighborhoods present in the simulation std::set<ID> global_neighborhoods; class DummyDataAccessor : public DataAccessor { public: virtual inline UInt getNbDataForElements(__attribute__((unused)) const Array<Element> & elements, __attribute__((unused)) SynchronizationTag tag) const { return 0; }; virtual inline void packElementData(__attribute__((unused)) CommunicationBuffer & buffer, __attribute__((unused)) const Array<Element> & element, __attribute__((unused)) SynchronizationTag tag) const {}; virtual inline void unpackElementData(__attribute__((unused)) CommunicationBuffer & buffer, __attribute__((unused)) const Array<Element> & element, __attribute__((unused)) SynchronizationTag tag) {}; }; DummyDataAccessor dummy_accessor; }; -__END_AKANTU__ +} // akantu /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "non_local_manager_inline_impl.cc" #endif /* __AKANTU_NON_LOCAL_MANAGER_HH__ */ diff --git a/src/model/common/non_local_toolbox/non_local_manager_inline_impl.cc b/src/model/common/non_local_toolbox/non_local_manager_inline_impl.cc index 1bb8c95dd..ea8412cc1 100644 --- a/src/model/common/non_local_toolbox/non_local_manager_inline_impl.cc +++ b/src/model/common/non_local_toolbox/non_local_manager_inline_impl.cc @@ -1,248 +1,248 @@ /** * @file non_local_manager_inline_impl.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Wed Nov 25 2015 * * @brief inline implementation of non-local manager functions * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "grid_synchronizer.hh" #include "synchronizer_registry.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NON_LOCAL_MANAGER_INLINE_IMPL_CC__ #define __AKANTU_NON_LOCAL_MANAGER_INLINE_IMPL_CC__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ inline void NonLocalManager::insertQuad(const IntegrationPoint & quad, const Vector<Real> & coords, const ID & neighborhood) { AKANTU_DEBUG_ASSERT(neighborhoods[neighborhood] != NULL, "The neighborhood " << neighborhood << "has not been created"); neighborhoods[neighborhood]->insertQuad(quad, coords); } /* -------------------------------------------------------------------------- */ inline void NonLocalManager::registerNeighborhood(const ID & neighborhood, const ID & weight_func_id) { /// check if neighborhood has already been created NeighborhoodMap::const_iterator it = neighborhoods.find(neighborhood); if (it == neighborhoods.end()) { this->createNeighborhood(weight_func_id, neighborhood); } } /* -------------------------------------------------------------------------- */ inline NonLocalNeighborhoodBase & NonLocalManager::getNeighborhood(const ID & name) const { AKANTU_DEBUG_IN(); NeighborhoodMap::const_iterator it = neighborhoods.find(name); AKANTU_DEBUG_ASSERT(it != neighborhoods.end(), "The neighborhood " << name << " is not registered"); AKANTU_DEBUG_OUT(); return *(it->second); } /* -------------------------------------------------------------------------- */ inline void NonLocalManager::computeWeights() { AKANTU_DEBUG_IN(); this->updateWeightFunctionInternals(); this->volumes.clear(); // NeighborhoodMap::iterator it = neighborhoods.begin(); // NeighborhoodMap::iterator end = neighborhoods.end(); // for (; it != end; ++it) // it->second->updateWeights(); /// loop over all the neighborhoods and call onElementsRemoved std::set<ID>::const_iterator global_neighborhood_it = global_neighborhoods.begin(); NeighborhoodMap::iterator it; for (; global_neighborhood_it != global_neighborhoods.end(); ++global_neighborhood_it) { it = neighborhoods.find(*global_neighborhood_it); if (it != neighborhoods.end()) it->second->updateWeights(); else { dummy_synchronizers[*global_neighborhood_it]->asynchronousSynchronize( dummy_accessor, _gst_mnl_weight); dummy_synchronizers[*global_neighborhood_it]->waitEndSynchronize( dummy_accessor, _gst_mnl_weight); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void NonLocalManager::updatePairLists() { AKANTU_DEBUG_IN(); /// compute the position of the quadrature points this->model.getFEEngine().computeIntegrationPointsCoordinates(quad_positions); NeighborhoodMap::iterator it = neighborhoods.begin(); NeighborhoodMap::iterator end = neighborhoods.end(); for (; it != end; ++it) it->second->updatePairList(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void NonLocalManager::registerNonLocalVariable( const ID & variable_name, const ID & nl_variable_name, UInt nb_component) { AKANTU_DEBUG_IN(); std::map<ID, NonLocalVariable *>::iterator non_local_variable_it = non_local_variables.find(variable_name); if (non_local_variable_it == non_local_variables.end()) non_local_variables[nl_variable_name] = new NonLocalVariable( variable_name, nl_variable_name, this->id, nb_component); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void NonLocalManager::registerNonLocalMaterial(Material & new_mat) { non_local_materials.push_back(&new_mat); } /* -------------------------------------------------------------------------- */ inline ElementTypeMapReal & NonLocalManager::registerWeightFunctionInternal(const ID & field_name) { AKANTU_DEBUG_IN(); std::map<ID, ElementTypeMapReal *>::const_iterator it = this->weight_function_internals.find(field_name); if (it == weight_function_internals.end()) { weight_function_internals[field_name] = new ElementTypeMapReal(field_name, id, memory_id); } return *(weight_function_internals[field_name]); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void NonLocalManager::updateWeightFunctionInternals() { std::map<ID, ElementTypeMapReal *>::const_iterator it = this->weight_function_internals.begin(); std::map<ID, ElementTypeMapReal *>::const_iterator end = this->weight_function_internals.end(); for (; it != end; ++it) { it->second->clear(); for (UInt g = _not_ghost; g <= _ghost; ++g) { GhostType ghost_type = (GhostType)g; this->flattenInternal(*(it->second), ghost_type, _ek_regular); } } } /* -------------------------------------------------------------------------- */ inline void NonLocalManager::nonLocalVariableToNeighborhood(const ID & variable_name, const ID & neighborhood) { NeighborhoodMap::const_iterator it = neighborhoods.find(neighborhood); AKANTU_DEBUG_ASSERT(it != neighborhoods.end(), "The neighborhood " << neighborhood << " is not registered"); it->second->registerNonLocalVariable(variable_name); } /* -------------------------------------------------------------------------- */ inline UInt NonLocalManager::getNbDataForElements(const Array<Element> & elements, const ID & id) const { UInt size = 0; UInt nb_quadrature_points = this->getModel().getNbIntegrationPoints(elements); std::map<ID, NonLocalVariable *>::const_iterator it = non_local_variables.find(id); AKANTU_DEBUG_ASSERT(it != non_local_variables.end(), "The non-local variable " << id << " is not registered"); size += it->second->nb_component * sizeof(Real) * nb_quadrature_points; return size; } /* -------------------------------------------------------------------------- */ inline void NonLocalManager::packElementData(CommunicationBuffer & buffer, const Array<Element> & elements, __attribute__((unused)) SynchronizationTag tag, const ID & id) const { std::map<ID, NonLocalVariable *>::const_iterator it = non_local_variables.find(id); AKANTU_DEBUG_ASSERT(it != non_local_variables.end(), "The non-local variable " << id << " is not registered"); DataAccessor::packElementalDataHelper<Real>( it->second->local, buffer, elements, true, this->model.getFEEngine()); } /* -------------------------------------------------------------------------- */ inline void NonLocalManager::unpackElementData(CommunicationBuffer & buffer, const Array<Element> & elements, __attribute__((unused)) SynchronizationTag tag, const ID & id) const { std::map<ID, NonLocalVariable *>::const_iterator it = non_local_variables.find(id); AKANTU_DEBUG_ASSERT(it != non_local_variables.end(), "The non-local variable " << id << " is not registered"); DataAccessor::unpackElementalDataHelper<Real>( it->second->local, buffer, elements, true, this->model.getFEEngine()); } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_NON_LOCAL_MANAGER_INLINE_IMPL_CC__ */ diff --git a/src/model/common/non_local_toolbox/non_local_neighborhood.hh b/src/model/common/non_local_toolbox/non_local_neighborhood.hh index 401b24f97..cbd6e7437 100644 --- a/src/model/common/non_local_toolbox/non_local_neighborhood.hh +++ b/src/model/common/non_local_toolbox/non_local_neighborhood.hh @@ -1,136 +1,136 @@ /** * @file non_local_neighborhood.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Wed Nov 25 2015 * * @brief Non-local neighborhood for non-local averaging based on * weight function * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NON_LOCAL_NEIGHBORHOOD_HH__ #define __AKANTU_NON_LOCAL_NEIGHBORHOOD_HH__ /* -------------------------------------------------------------------------- */ #include "base_weight_function.hh" #include "non_local_neighborhood_base.hh" #include "parsable.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class NonLocalManager; class TestWeightFunction; } -__BEGIN_AKANTU__ +namespace akantu { template<class WeightFunction = BaseWeightFunction> class NonLocalNeighborhood : public NonLocalNeighborhoodBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NonLocalNeighborhood(NonLocalManager & manager, const ElementTypeMapReal & quad_coordinates, const ID & id = "neighborhood", const MemoryID & memory_id = 0); virtual ~NonLocalNeighborhood(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// compute the weights for non-local averaging void computeWeights(); /// save the pair of weights in a file void saveWeights(const std::string & filename) const; /// compute the non-local counter part for a given element type map virtual void weightedAverageOnNeighbours(const ElementTypeMapReal & to_accumulate, ElementTypeMapReal & accumulated, UInt nb_degree_of_freedom, const GhostType & ghost_type2) const; /// update the weights based on the weight function void updateWeights(); /// register a new non-local variable in the neighborhood virtual void registerNonLocalVariable(const ID & id); protected: virtual inline UInt getNbDataForElements(const Array<Element> & elements, SynchronizationTag tag) const; virtual inline void packElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag) const; virtual inline void unpackElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag); /* -------------------------------------------------------------------------- */ /* Accessor */ /* -------------------------------------------------------------------------- */ AKANTU_GET_MACRO(NonLocalManager, *non_local_manager, const NonLocalManager &); AKANTU_GET_MACRO_NOT_CONST(NonLocalManager, *non_local_manager, NonLocalManager &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// Pointer to non-local manager class NonLocalManager * non_local_manager; /// the weights associated to the pairs Array<Real> * pair_weight[2]; /// weight function WeightFunction * weight_function; }; -__END_AKANTU__ +} // akantu /* -------------------------------------------------------------------------- */ /* Implementation of template functions */ /* -------------------------------------------------------------------------- */ #include "non_local_neighborhood_tmpl.hh" /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "non_local_neighborhood_inline_impl.cc" #endif /* __AKANTU_NON_LOCAL_NEIGHBORHOOD_HH__ */ diff --git a/src/model/common/non_local_toolbox/non_local_neighborhood_base.cc b/src/model/common/non_local_toolbox/non_local_neighborhood_base.cc index ec6d58a8d..0413c8735 100644 --- a/src/model/common/non_local_toolbox/non_local_neighborhood_base.cc +++ b/src/model/common/non_local_toolbox/non_local_neighborhood_base.cc @@ -1,113 +1,113 @@ /** * @file non_local_neighborhood_base.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sat Sep 26 2015 * @date last modification: Wed Nov 25 2015 * * @brief Implementation of non-local neighborhood base * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "non_local_neighborhood_base.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ NonLocalNeighborhoodBase::NonLocalNeighborhoodBase(const SolidMechanicsModel & model, const ElementTypeMapReal & quad_coordinates, const ID & id, const MemoryID & memory_id) : NeighborhoodBase(model, quad_coordinates, id, memory_id), Parsable(_st_non_local, id) { AKANTU_DEBUG_IN(); this->registerParam("radius" , neighborhood_radius , 100., _pat_parsable | _pat_readable , "Non local radius"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ NonLocalNeighborhoodBase::~NonLocalNeighborhoodBase() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void NonLocalNeighborhoodBase::createGridSynchronizer() { this->is_creating_grid = true; std::set<SynchronizationTag> tags; tags.insert(_gst_mnl_for_average); tags.insert(_gst_mnl_weight); std::stringstream sstr; sstr << getID() << ":grid_synchronizer"; this->grid_synchronizer = GridSynchronizer::createGridSynchronizer(this->model.getMesh(), *spatial_grid, sstr.str(), synch_registry, tags, 0, false); this->is_creating_grid = false; } /* -------------------------------------------------------------------------- */ void NonLocalNeighborhoodBase::cleanupExtraGhostElements(std::set<Element> & relevant_ghost_elements) { PairList::const_iterator first_pair = pair_list[_ghost].begin(); PairList::const_iterator last_pair = pair_list[_ghost].end(); for(;first_pair != last_pair; ++first_pair) { const IntegrationPoint & q2 = first_pair->second; relevant_ghost_elements.insert(q2); } Array<Element> ghosts_to_erase(0); Mesh & mesh = this->model.getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _ghost); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _ghost); Element element; element.ghost_type = _ghost; std::set<Element>::const_iterator end = relevant_ghost_elements.end(); for(; it != last_type; ++it) { element.type = *it; UInt nb_ghost_elem = mesh.getNbElement(*it, _ghost); for (UInt g = 0; g < nb_ghost_elem; ++g) { element.element = g; if (relevant_ghost_elements.find(element) == end) { ghosts_to_erase.push_back(element); } } } /// remove the unneccessary ghosts from the synchronizer this->grid_synchronizer->removeElements(ghosts_to_erase); } -__END_AKANTU__ +} // akantu diff --git a/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh b/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh index c00a8b6a8..3edb674e1 100644 --- a/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh +++ b/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh @@ -1,127 +1,127 @@ /** * @file non_local_neighborhood_base.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sat Sep 26 2015 * @date last modification: Wed Nov 25 2015 * * @brief Non-local neighborhood base class * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NON_LOCAL_NEIGHBORHOOD_BASE_HH__ #define __AKANTU_NON_LOCAL_NEIGHBORHOOD_BASE_HH__ /* -------------------------------------------------------------------------- */ #include "neighborhood_base.hh" #include "parsable.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class NonLocalNeighborhoodBase : public NeighborhoodBase, public Parsable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NonLocalNeighborhoodBase(const SolidMechanicsModel & model, const ElementTypeMapReal & quad_coordinates, const ID & id = "non_local_neighborhood", const MemoryID & memory_id = 0); virtual ~NonLocalNeighborhoodBase(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// create grid synchronizer and exchange ghost cells virtual void createGridSynchronizer(); /// compute weights, for instance needed for non-local damage computation virtual void computeWeights(){}; /// compute the non-local counter part for a given element type map virtual void weightedAverageOnNeighbours( __attribute__((unused)) const ElementTypeMapReal & to_accumulate, __attribute__((unused)) ElementTypeMapReal & accumulated, __attribute__((unused)) UInt nb_degree_of_freedom, __attribute__((unused)) const GhostType & ghost_type2) const {}; /// update the weights for the non-local averaging virtual void updateWeights(){}; /// register a new non-local variable in the neighborhood virtual void registerNonLocalVariable(__attribute__((unused)) const ID & id){}; /// clean up the unneccessary ghosts void cleanupExtraGhostElements(std::set<Element> & relevant_ghost_elements); protected: /// create the grid void createGrid(); /* -------------------------------------------------------------------------- */ /* DataAccessor inherited members */ /* -------------------------------------------------------------------------- */ public: virtual inline UInt getNbDataForElements(__attribute__((unused)) const Array<Element> & elements, __attribute__((unused)) SynchronizationTag tag) const { return 0; }; virtual inline void packElementData(__attribute__((unused)) CommunicationBuffer & buffer, __attribute__((unused)) const Array<Element> & elements, __attribute__((unused)) SynchronizationTag tag) const {}; virtual inline void unpackElementData(__attribute__((unused)) CommunicationBuffer & buffer, __attribute__((unused)) const Array<Element> & elements, __attribute__((unused)) SynchronizationTag tag){}; /* -------------------------------------------------------------------------- */ /* Accessors */ /* -------------------------------------------------------------------------- */ public: AKANTU_GET_MACRO(NonLocalVariables, non_local_variables, const std::set<ID> &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// list of non-local variables associated to the neighborhood std::set<ID> non_local_variables; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_NON_LOCAL_NEIGHBORHOOD_BASE_HH__ */ diff --git a/src/model/common/non_local_toolbox/non_local_neighborhood_inline_impl.cc b/src/model/common/non_local_toolbox/non_local_neighborhood_inline_impl.cc index 636c2bcea..ac85c64a0 100644 --- a/src/model/common/non_local_toolbox/non_local_neighborhood_inline_impl.cc +++ b/src/model/common/non_local_toolbox/non_local_neighborhood_inline_impl.cc @@ -1,95 +1,95 @@ /** * @file non_local_neighborhood_inline_impl.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Oct 06 2015 * @date last modification: Wed Nov 25 2015 * * @brief Implementation of inline functions of non-local neighborhood class * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NON_LOCAL_NEIGHBORHOOD_INLINE_IMPL_CC__ #define __AKANTU_NON_LOCAL_NEIGHBORHOOD_INLINE_IMPL_CC__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<class WeightFunction> inline UInt NonLocalNeighborhood<WeightFunction>::getNbDataForElements(const Array<Element> & elements, SynchronizationTag tag) const { UInt size = 0; if(tag == _gst_mnl_for_average) { std::set<ID>::const_iterator it = non_local_variables.begin(); std::set<ID>::const_iterator end = non_local_variables.end(); for(;it != end; ++it) { size += this->non_local_manager->getNbDataForElements(elements, *it); } } size += this->weight_function->getNbDataForElements(elements, tag); return size; } /* -------------------------------------------------------------------------- */ template<class WeightFunction> inline void NonLocalNeighborhood<WeightFunction>::packElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag) const { if(tag == _gst_mnl_for_average) { std::set<ID>::const_iterator it = non_local_variables.begin(); std::set<ID>::const_iterator end = non_local_variables.end(); for(;it != end; ++it) { this->non_local_manager->packElementData(buffer, elements, tag, *it); } } this->weight_function->packElementData(buffer, elements, tag); } /* -------------------------------------------------------------------------- */ template<class WeightFunction> inline void NonLocalNeighborhood<WeightFunction>::unpackElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag) { if(tag == _gst_mnl_for_average) { std::set<ID>::const_iterator it = non_local_variables.begin(); std::set<ID>::const_iterator end = non_local_variables.end(); for(;it != end; ++it) { this->non_local_manager->unpackElementData(buffer, elements, tag, *it); } } this->weight_function->unpackElementData(buffer, elements, tag); } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_NON_LOCAL_NEIGHBORHOOD_INLINE_IMPL_CC__ */ diff --git a/src/model/common/non_local_toolbox/non_local_neighborhood_tmpl.hh b/src/model/common/non_local_toolbox/non_local_neighborhood_tmpl.hh index 39af89d5d..9d12110d0 100644 --- a/src/model/common/non_local_toolbox/non_local_neighborhood_tmpl.hh +++ b/src/model/common/non_local_toolbox/non_local_neighborhood_tmpl.hh @@ -1,286 +1,286 @@ /** * @file non_local_neighborhood_tmpl.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Sep 28 2015 * @date last modification: Wed Nov 25 2015 * * @brief Implementation of class non-local neighborhood * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "non_local_manager.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NON_LOCAL_NEIGHBORHOOD_TMPL_HH__ #define __AKANTU_NON_LOCAL_NEIGHBORHOOD_TMPL_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<class WeightFunction> NonLocalNeighborhood<WeightFunction>::NonLocalNeighborhood(NonLocalManager & manager, const ElementTypeMapReal & quad_coordinates, const ID & id, const MemoryID & memory_id) : NonLocalNeighborhoodBase(manager.getModel(), quad_coordinates, id, memory_id), non_local_manager(&manager) { AKANTU_DEBUG_IN(); for(UInt gt = _not_ghost; gt <= _ghost; ++gt) { GhostType ghost_type = (GhostType) gt; pair_weight[ghost_type] = NULL; } this->weight_function = new WeightFunction(this->getNonLocalManager()); this->registerSubSection(_st_weight_function, "weight_parameter", *weight_function); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<class WeightFunction> NonLocalNeighborhood<WeightFunction>::~NonLocalNeighborhood() { AKANTU_DEBUG_IN(); for(UInt gt = _not_ghost; gt <= _ghost; ++gt) { GhostType ghost_type = (GhostType) gt; delete pair_weight[ghost_type]; } delete weight_function; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<class WeightFunction> void NonLocalNeighborhood<WeightFunction>::computeWeights() { AKANTU_DEBUG_IN(); this->weight_function->setRadius(this->neighborhood_radius); Vector<Real> q1_coord(this->spatial_dimension); Vector<Real> q2_coord(this->spatial_dimension); UInt nb_weights_per_pair = 2; /// w1: q1->q2, w2: q2->q1 /// get the elementtypemap for the neighborhood volume for each quadrature point ElementTypeMapReal & quadrature_points_volumes = this->non_local_manager->getVolumes(); /// update the internals of the weight function if applicable (not /// all the weight functions have internals and do noting in that /// case) weight_function->updateInternals(); for(UInt gt = _not_ghost; gt <= _ghost; ++gt) { GhostType ghost_type = (GhostType) gt; /// allocate the array to store the weight, if it doesn't exist already if(!(pair_weight[ghost_type])) { std::string ghost_id = ""; if (ghost_type == _ghost) ghost_id = ":ghost"; std::stringstream sstr; sstr << this->id <<":pair_weight:" << ghost_id; pair_weight[ghost_type] = new Array<Real>(0, nb_weights_per_pair, sstr.str()); } /// resize the array to the correct size pair_weight[ghost_type]->resize(pair_list[ghost_type].size()); /// set entries to zero pair_weight[ghost_type]->clear(); /// loop over all pairs in the current pair list array and their corresponding weights PairList::const_iterator first_pair = pair_list[ghost_type].begin(); PairList::const_iterator last_pair = pair_list[ghost_type].end(); Array<Real>::vector_iterator weight_it = pair_weight[ghost_type]->begin(nb_weights_per_pair); // Compute the weights for(;first_pair != last_pair; ++first_pair, ++weight_it) { Vector<Real> & weight = *weight_it; const IntegrationPoint & q1 = first_pair->first; const IntegrationPoint & q2 = first_pair->second; /// get the coordinates for the given pair of quads Array<Real>::const_vector_iterator coords_type_1_it = this->quad_coordinates(q1.type, q1.ghost_type).begin(this->spatial_dimension); q1_coord = coords_type_1_it[q1.global_num]; Array<Real>::const_vector_iterator coords_type_2_it = this->quad_coordinates(q2.type, q2.ghost_type).begin(this->spatial_dimension); q2_coord = coords_type_2_it[q2.global_num]; Array<Real> & quad_volumes_1 = quadrature_points_volumes(q1.type, q1.ghost_type); const Array<Real> & jacobians_2 = this->non_local_manager->getJacobians(q2.type, q2.ghost_type); const Real & q2_wJ = jacobians_2(q2.global_num); /// compute distance between the two quadrature points Real r = q1_coord.distance(q2_coord); /// compute the weight for averaging on q1 based on the distance Real w1 = this->weight_function->operator()(r, q1, q2); weight(0) = q2_wJ * w1; quad_volumes_1(q1.global_num) += weight(0); if(q2.ghost_type != _ghost && q1.global_num != q2.global_num) { const Array<Real> & jacobians_1 = this->non_local_manager->getJacobians(q1.type, q1.ghost_type); Array<Real> & quad_volumes_2 = quadrature_points_volumes(q2.type, q2.ghost_type); /// compute the weight for averaging on q2 const Real & q1_wJ = jacobians_1(q1.global_num); Real w2 = this->weight_function->operator()(r, q2, q1); weight(1) = q1_wJ * w2; quad_volumes_2(q2.global_num) += weight(1); } else weight(1) = 0.; } } /// normalize the weights for(UInt gt = _not_ghost; gt <= _ghost; ++gt) { GhostType ghost_type2 = (GhostType) gt; PairList::const_iterator first_pair = pair_list[ghost_type2].begin(); PairList::const_iterator last_pair = pair_list[ghost_type2].end(); Array<Real>::vector_iterator weight_it = pair_weight[ghost_type2]->begin(nb_weights_per_pair); // Compute the weights for(;first_pair != last_pair; ++first_pair, ++weight_it) { Vector<Real> & weight = *weight_it; const IntegrationPoint & q1 = first_pair->first; const IntegrationPoint & q2 = first_pair->second; Array<Real> & quad_volumes_1 = quadrature_points_volumes(q1.type, q1.ghost_type); Array<Real> & quad_volumes_2 = quadrature_points_volumes(q2.type, q2.ghost_type); Real q1_volume = quad_volumes_1(q1.global_num); weight(0) *= 1. / q1_volume; if(ghost_type2 != _ghost) { Real q2_volume = quad_volumes_2(q2.global_num); weight(1) *= 1. / q2_volume; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<class WeightFunction> void NonLocalNeighborhood<WeightFunction>::saveWeights(const std::string & filename) const { std::ofstream pout; std::stringstream sstr; StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int prank = comm.whoAmI(); sstr << filename << "." << prank; pout.open(sstr.str().c_str()); for (UInt gt = _not_ghost; gt <= _ghost; ++gt) { GhostType ghost_type = (GhostType) gt; AKANTU_DEBUG_ASSERT((pair_weight[ghost_type]), "the weights have not been computed yet"); Array<Real> & weights = *(pair_weight[ghost_type]); Array<Real>::const_vector_iterator weights_it = weights.begin(2); for (UInt i = 0; i < weights.getSize(); ++i, ++weights_it) pout << "w1: " << (*weights_it)(0) <<" w2: " << (*weights_it)(1) << std::endl; } } /* -------------------------------------------------------------------------- */ template<class WeightFunction> void NonLocalNeighborhood<WeightFunction>::weightedAverageOnNeighbours(const ElementTypeMapReal & to_accumulate, ElementTypeMapReal & accumulated, UInt nb_degree_of_freedom, const GhostType & ghost_type2) const { AKANTU_DEBUG_IN(); std::set<ID>::iterator it = non_local_variables.find(accumulated.getName()); ///do averaging only for variables registered in the neighborhood if (it != non_local_variables.end()) { PairList::const_iterator first_pair = pair_list[ghost_type2].begin(); PairList::const_iterator last_pair = pair_list[ghost_type2].end(); Array<Real>::vector_iterator weight_it = pair_weight[ghost_type2]->begin(2); // Compute the weights for(;first_pair != last_pair; ++first_pair, ++weight_it) { Vector<Real> & weight = *weight_it; const IntegrationPoint & q1 = first_pair->first; const IntegrationPoint & q2 = first_pair->second; const Array<Real> & to_acc_1 = to_accumulate(q1.type, q1.ghost_type); Array<Real> & acc_1 = accumulated(q1.type, q1.ghost_type); const Array<Real> & to_acc_2 = to_accumulate(q2.type, q2.ghost_type); Array<Real> & acc_2 = accumulated(q2.type, q2.ghost_type); for(UInt d = 0; d < nb_degree_of_freedom; ++d) { acc_1(q1.global_num, d) += weight(0) * to_acc_2(q2.global_num, d); } if(ghost_type2 != _ghost) { for(UInt d = 0; d < nb_degree_of_freedom; ++d) { acc_2(q2.global_num, d) += weight(1) * to_acc_1(q1.global_num, d); } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<class WeightFunction> void NonLocalNeighborhood<WeightFunction>::updateWeights() { // Update the weights for the non local variable averaging if(this->weight_function->getUpdateRate() && (this->non_local_manager->getNbStressCalls() % this->weight_function->getUpdateRate() == 0)) { this->synch_registry->asynchronousSynchronize(_gst_mnl_weight); this->synch_registry->waitEndSynchronize(_gst_mnl_weight); this->computeWeights(); } } /* -------------------------------------------------------------------------- */ template<class WeightFunction> void NonLocalNeighborhood<WeightFunction>::registerNonLocalVariable(const ID & id) { this->non_local_variables.insert(id); } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_NON_LOCAL_NEIGHBORHOOD_TMPL__ */ diff --git a/src/model/dof_manager_default_inline_impl.cc b/src/model/dof_manager_default_inline_impl.cc index b26b77f4c..c3ef864b2 100644 --- a/src/model/dof_manager_default_inline_impl.cc +++ b/src/model/dof_manager_default_inline_impl.cc @@ -1,105 +1,105 @@ /** * @file dof_manager_default_inline_impl.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Wed Aug 12 10:57:47 2015 * * @brief Implementation of the DOFManagerDefault 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "dof_manager_default.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_DOF_MANAGER_DEFAULT_INLINE_IMPL_CC__ #define __AKANTU_DOF_MANAGER_DEFAULT_INLINE_IMPL_CC__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ inline bool DOFManagerDefault::isLocalOrMasterDOF(UInt dof_num) { Int dof_type = this->dofs_type(dof_num); return (dof_type == Int(_nt_normal)) || (dof_type == Int(_nt_master)); } /* -------------------------------------------------------------------------- */ inline bool DOFManagerDefault::isSlaveDOF(UInt dof_num) { Int dof_type = this->dofs_type(dof_num); return (dof_type >= 0); } /* -------------------------------------------------------------------------- */ inline const Array<UInt> & DOFManagerDefault::getLocalEquationNumbers(const ID & dof_id) const { return this->getDOFData(dof_id).local_equation_number; } inline const Array<UInt> & DOFManagerDefault::getDOFsAssociatedNodes(const ID & dof_id) const { const DOFDataDefault & dof_data = this->getDOFDataTyped<DOFDataDefault>(dof_id); return dof_data.associated_nodes; } /* -------------------------------------------------------------------------- */ inline void DOFManagerDefault::extractElementEquationNumber( const Array<UInt> & equation_numbers, const Vector<UInt> & connectivity, UInt nb_degree_of_freedom, Vector<UInt> & element_equation_number) { for (UInt i = 0, ld = 0; i < connectivity.size(); ++i) { UInt n = connectivity(i); for (UInt d = 0; d < nb_degree_of_freedom; ++d, ++ld) { element_equation_number(ld) = equation_numbers(n * nb_degree_of_freedom + d); } } } /* -------------------------------------------------------------------------- */ inline UInt DOFManagerDefault::localToGlobalEquationNumber(UInt local) const { return this->global_equation_number(local); } /* -------------------------------------------------------------------------- */ inline bool DOFManagerDefault::hasGlobalEquationNumber(UInt global) const { auto it = this->global_to_local_mapping.find(global); return (it != this->global_to_local_mapping.end()); } /* -------------------------------------------------------------------------- */ inline UInt DOFManagerDefault::globalToLocalEquationNumber(UInt global) const { auto it = this->global_to_local_mapping.find(global); AKANTU_DEBUG_ASSERT(it != this->global_to_local_mapping.end(), "This global equation number " << global << " does not exists in " << this->id); return it->second; } /* -------------------------------------------------------------------------- */ inline Int DOFManagerDefault::getDOFType(UInt local_id) const { return this->dofs_type(local_id); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DOF_MANAGER_DEFAULT_INLINE_IMPL_CC_ */ diff --git a/src/model/dof_manager_petsc.cc b/src/model/dof_manager_petsc.cc index 14f47fdb6..b34b3d7b5 100644 --- a/src/model/dof_manager_petsc.cc +++ b/src/model/dof_manager_petsc.cc @@ -1,396 +1,396 @@ /** * @file dof_manager_petsc.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Mon Oct 5 21:19:58 2015 * * @brief DOFManaterPETSc is the PETSc implementation of the DOFManager * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "dof_manager_petsc.hh" #include "cppargparse.hh" #if defined(AKANTU_USE_MPI) #include "static_communicator.hh" #include "mpi_type_wrapper.hh" #endif /* -------------------------------------------------------------------------- */ #include <petscsys.h> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { #if not defined(PETSC_CLANGUAGE_CXX) /// small hack to use the c binding of petsc when the cxx binding does notation /// exists int aka_PETScError(int ierr) { CHKERRQ(ierr); return 0; } #endif UInt DOFManagerPETSc::petsc_dof_manager_instances = 0; /// Error handler to make PETSc errors caught by Akantu #if PETSC_VERSION_MAJOR >= 3 && PETSC_VERSION_MINOR >= 5 static PetscErrorCode PETScErrorHandler(MPI_Comm, int line, const char * dir, const char * file, PetscErrorCode number, PetscErrorType type, const char * message, void *) { AKANTU_DEBUG_ERROR("An error occured in PETSc in file \"" << file << ":" << line << "\" - PetscErrorCode " << number << " - \"" << message << "\""); } #else static PetscErrorCode PETScErrorHandler(MPI_Comm, int line, const char * func, const char * dir, const char * file, PetscErrorCode number, PetscErrorType type, const char * message, void *) { AKANTU_DEBUG_ERROR("An error occured in PETSc in file \"" << file << ":" << line << "\" - PetscErrorCode " << number << " - \"" << message << "\""); } #endif /* -------------------------------------------------------------------------- */ DOFManagerPETSc::DOFManagerPETSc(const ID & id, const MemoryID & memory_id) : DOFManager(id, memory_id) { // check if the akantu types and PETSc one are consistant #if __cplusplus > 199711L static_assert(sizeof(Int) == sizeof(PetscInt), "The integer type of Akantu does not match the one from PETSc"); static_assert(sizeof(Real) == sizeof(PetscReal), "The integer type of Akantu does not match the one from PETSc"); #else AKANTU_DEBUG_ASSERT( sizeof(Int) == sizeof(PetscInt), "The integer type of Akantu does not match the one from PETSc"); AKANTU_DEBUG_ASSERT( sizeof(Real) == sizeof(PetscReal), "The integer type of Akantu does not match the one from PETSc"); #endif if (this->petsc_dof_manager_instances == 0) { #if defined(AKANTU_USE_MPI) StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); const StaticCommunicatorMPI & mpi_st_comm = dynamic_cast<const StaticCommunicatorMPI &>( comm.getRealStaticCommunicator()); this->mpi_communicator = mpi_st_comm.getMPITypeWrapper().getMPICommunicator(); #else this->mpi_communicator = PETSC_COMM_SELF; #endif cppargparse::ArgumentParser & argparser = getStaticArgumentParser(); int & argc = argparser.getArgC(); char **& argv = argparser.getArgV(); PetscErrorCode petsc_error = PetscInitialize(&argc, &argv, NULL, NULL); if (petsc_error != 0) { AKANTU_DEBUG_ERROR( "An error occured while initializing Petsc (PetscErrorCode " << petsc_error << ")"); } PetscPushErrorHandler(PETScErrorHandler, NULL); this->petsc_dof_manager_instances++; } VecCreate(PETSC_COMM_WORLD, &this->residual); VecCreate(PETSC_COMM_WORLD, &this->solution); } /* -------------------------------------------------------------------------- */ DOFManagerPETSc::~DOFManagerPETSc() { PetscErrorCode ierr; ierr = VecDestroy(&(this->residual)); CHKERRXX(ierr); ierr = VecDestroy(&(this->solution)); CHKERRXX(ierr); this->petsc_dof_manager_instances--; if (this->petsc_dof_manager_instances == 0) { PetscFinalize(); } } /* -------------------------------------------------------------------------- */ void DOFManagerPETSc::registerDOFs(const ID & dof_id, Array<Real> & dofs_array, DOFSupportType & support_type) { DOFManager::registerDOFs(dof_id, dofs_array, support_type); PetscErrorCode ierr; PetscInt current_size; ierr = VecGetSize(this->residual, ¤t_size); CHKERRXX(ierr); if (current_size == 0) { // first time vector is set PetscInt local_size = this->pure_local_system_size; ierr = VecSetSizes(this->residual, local_size, PETSC_DECIDE); CHKERRXX(ierr); ierr = VecSetFromOptions(this->residual); CHKERRXX(ierr); #ifndef AKANTU_NDEBUG PetscInt global_size; ierr = VecGetSize(this->residual, &global_size); CHKERRXX(ierr); AKANTU_DEBUG_ASSERT(this->system_size == UInt(global_size), "The local value of the system size does not match the " "one determined by PETSc"); #endif PetscInt start_dof, end_dof; VecGetOwnershipRange(this->residual, &start_dof, &end_dof); PetscInt * global_indices = new PetscInt[local_size]; global_indices[0] = start_dof; for (PetscInt d = 0; d < local_size; d++) global_indices[d + 1] = global_indices[d] + 1; // To be change if we switch to a block definition #if PETSC_VERSION_MAJOR >= 3 && PETSC_VERSION_MINOR >= 5 ISLocalToGlobalMappingCreate(this->communicator, 1, local_size, global_indices, PETSC_COPY_VALUES, &this->is_ltog); #else ISLocalToGlobalMappingCreate(this->communicator, local_size, global_indices, PETSC_COPY_VALUES, &this->is_ltog); #endif VecSetLocalToGlobalMapping(this->residual, this->is_ltog); delete[] global_indices; ierr = VecDuplicate(this->residual, &this->solution); CHKERRXX(ierr); } else { // this is an update of the object already created AKANTU_DEBUG_TO_IMPLEMENT(); } /// set the solution to zero // ierr = VecZeroEntries(this->solution); // CHKERRXX(ierr); } /* -------------------------------------------------------------------------- */ /** * This function creates the non-zero pattern of the PETSc matrix. In * PETSc the parallel matrix is partitioned across processors such * that the first m0 rows belong to process 0, the next m1 rows belong * to process 1, the next m2 rows belong to process 2 etc.. where * m0,m1,m2,.. are the input parameter 'm'. i.e each processor stores * values corresponding to [m x N] submatrix * (http://www.mcs.anl.gov/petsc/). * @param mesh mesh discretizing the domain we want to analyze * @param dof_synchronizer dof synchronizer that maps the local * dofs to the global dofs and the equation numbers, i.e., the * position at which the dof is assembled in the matrix */ // void SparseMatrixPETSc::buildProfile(const Mesh & mesh, // const DOFSynchronizer & // dof_synchronizer, // UInt nb_degree_of_freedom) { // AKANTU_DEBUG_IN(); // // clearProfile(); // this->dof_synchronizer = &const_cast<DOFSynchronizer &>(dof_synchronizer); // this->setSize(); // PetscErrorCode ierr; // /// resize arrays to store the number of nonzeros in each row // this->d_nnz.resize(this->local_size); // this->o_nnz.resize(this->local_size); // /// set arrays to zero everywhere // this->d_nnz.set(0); // this->o_nnz.set(0); // // if(irn_jcn_to_k) delete irn_jcn_to_k; // // irn_jcn_to_k = new std::map<std::pair<UInt, UInt>, UInt>; // coordinate_list_map::iterator irn_jcn_k_it; // Int * eq_nb_val = dof_synchronizer.getGlobalDOFEquationNumbers().storage(); // UInt nb_global_dofs = dof_synchronizer.getNbGlobalDOFs(); // Array<Int> index_pair(2); // /// Loop over all the ghost types // for (ghost_type_t::iterator gt = ghost_type_t::begin(); // gt != ghost_type_t::end(); ++gt) { // const GhostType & ghost_type = *gt; // Mesh::type_iterator it = // mesh.firstType(mesh.getSpatialDimension(), ghost_type, // _ek_not_defined); // Mesh::type_iterator end = // mesh.lastType(mesh.getSpatialDimension(), ghost_type, // _ek_not_defined); // for (; it != end; ++it) { // UInt nb_element = mesh.getNbElement(*it, ghost_type); // UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); // UInt size_mat = nb_nodes_per_element * nb_degree_of_freedom; // UInt * conn_val = mesh.getConnectivity(*it, ghost_type).storage(); // Int * local_eq_nb_val = // new Int[nb_degree_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_degree_of_freedom; ++d) { // /** // * !!!!!!Careful!!!!!! This is a ugly fix. @todo this is a // * very ugly fix, because the offset for the global // * equation number, where the dof will be assembled, is // * hardcoded. In the future a class dof manager has to be // * added to Akantu to handle the mapping between the dofs // * and the equation numbers // * // */ // *tmp_local_eq_nb_val++ = // eq_nb_val[n * nb_degree_of_freedom + d] - // (dof_synchronizer.isPureGhostDOF(n * nb_degree_of_freedom + // d) // ? nb_global_dofs // : 0); // } // } // for (UInt i = 0; i < size_mat; ++i) { // Int c_irn = local_eq_nb_val[i]; // UInt j_start = 0; // for (UInt j = j_start; j < size_mat; ++j) { // Int c_jcn = local_eq_nb_val[j]; // index_pair(0) = c_irn; // index_pair(1) = c_jcn; // AOApplicationToPetsc(this->petsc_matrix_wrapper->ao, 2, // index_pair.storage()); // if (index_pair(0) >= first_global_index && // index_pair(0) < first_global_index + this->local_size) { // KeyCOO irn_jcn = keyPETSc(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; // // check if node is slave node // if (index_pair(1) >= first_global_index && // index_pair(1) < first_global_index + this->local_size) // this->d_nnz(index_pair(0) - first_global_index) += 1; // else // this->o_nnz(index_pair(0) - first_global_index) += 1; // nb_non_zero++; // } // } // } // } // conn_val += nb_nodes_per_element; // } // delete[] local_eq_nb_val; // } // } // // /// for pbc @todo correct it for parallel // // if(StaticCommunicator::getStaticCommunicator().getNbProc() == 1) { // // for (UInt i = 0; i < size; ++i) { // // KeyCOO irn_jcn = key(i, i); // // 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(i + 1); // // jcn.push_back(i + 1); // // nb_non_zero++; // // } // // } // // } // // std::string mat_type; // // mat_type.resize(20, 'a'); // // std::cout << "MatType: " << mat_type << std::endl; // // const char * mat_type_ptr = mat_type.c_str(); // MatType type; // MatGetType(this->petsc_matrix_wrapper->mat, &type); // /// std::cout << "the matrix type is: " << type << std::endl; // /** // * PETSc will use only one of the following preallocation commands // * depending on the matrix type and ignore the rest. Note that for // * the block matrix format a block size of 1 is used. This might // * result in bad performance. @todo For better results implement // * buildProfile() with larger block size. // * // */ // /// build profile: // if (strcmp(type, MATSEQAIJ) == 0) { // ierr = MatSeqAIJSetPreallocation(this->petsc_matrix_wrapper->mat, 0, // d_nnz.storage()); // CHKERRXX(ierr); // } else if ((strcmp(type, MATMPIAIJ) == 0)) { // ierr = MatMPIAIJSetPreallocation(this->petsc_matrix_wrapper->mat, 0, // d_nnz.storage(), 0, o_nnz.storage()); // CHKERRXX(ierr); // } else { // AKANTU_DEBUG_ERROR("The type " << type // << " of PETSc matrix is not handled by" // << " akantu in the preallocation step"); // } // // ierr = MatSeqSBAIJSetPreallocation(this->petsc_matrix_wrapper->mat, 1, // // 0, d_nnz.storage()); CHKERRXX(ierr); // if (this->sparse_matrix_type == _symmetric) { // /// set flag for symmetry to enable ICC/Cholesky preconditioner // ierr = MatSetOption(this->petsc_matrix_wrapper->mat, MAT_SYMMETRIC, // PETSC_TRUE); // CHKERRXX(ierr); // /// set flag for symmetric positive definite // ierr = MatSetOption(this->petsc_matrix_wrapper->mat, MAT_SPD, // PETSC_TRUE); // CHKERRXX(ierr); // } // /// once the profile has been build ignore any new nonzero locations // ierr = MatSetOption(this->petsc_matrix_wrapper->mat, // MAT_NEW_NONZERO_LOCATIONS, PETSC_TRUE); // CHKERRXX(ierr); // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/dof_manager_petsc.hh b/src/model/dof_manager_petsc.hh index e9e01bba1..0a8140a14 100644 --- a/src/model/dof_manager_petsc.hh +++ b/src/model/dof_manager_petsc.hh @@ -1,172 +1,172 @@ /** * @file dof_manager_petsc.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Tue Aug 11 14:06:18 2015 * * @brief PETSc implementation of the dof manager * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "dof_manager.hh" /* -------------------------------------------------------------------------- */ #include <petscvec.h> #include <petscis.h> /* -------------------------------------------------------------------------- */ #if not defined(PETSC_CLANGUAGE_CXX) extern int aka_PETScError(int ierr); #define CHKERRXX(x) \ do { \ int error = aka_PETScError(x); \ if (error != 0) { \ AKANTU_EXCEPTION("Error in PETSC"); \ } \ } while (0) #endif #ifndef __AKANTU_DOF_MANAGER_PETSC_HH__ #define __AKANTU_DOF_MANAGER_PETSC_HH__ -__BEGIN_AKANTU__ +namespace akantu { class SparseMatrixPETSc; class DOFManagerPETSc : public DOFManager { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: DOFManagerPETSc(const ID & id = "dof_manager_petsc", const MemoryID & memory_id = 0); DOFManagerPETSc(Mesh & mesh, const ID & id = "dof_manager_petsc", const MemoryID & memory_id = 0); virtual ~DOFManagerPETSc(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// register an array of degree of freedom void registerDOFs(const ID & dof_id, Array<Real> & dofs_array, DOFSupportType & support_type); /// Assemble an array to the global residual array virtual void assembleToResidual(const ID & dof_id, const Array<Real> & array_to_assemble, Real scale_factor = 1.); /** * Assemble elementary values to the global residual array. The dof number is * implicitly considered as conn(el, n) * nb_nodes_per_element + d. * With 0 < n < nb_nodes_per_element and 0 < d < nb_dof_per_node **/ virtual void assembleElementalArrayResidual( const ID & dof_id, const Array<Real> & array_to_assemble, const ElementType & type, const GhostType & ghost_type, Real scale_factor = 1.); /** * Assemble elementary values to the global residual array. The dof number is * implicitly considered as conn(el, n) * nb_nodes_per_element + d. * With 0 < n < nb_nodes_per_element and 0 < d < nb_dof_per_node **/ virtual void assembleElementalMatricesToMatrix( const ID & matrix_id, const ID & dof_id, const Array<Real> & elementary_mat, const ElementType & type, const GhostType & ghost_type, const MatrixType & elemental_matrix_type, const Array<UInt> & filter_elements); protected: /// Get the part of the solution corresponding to the dof_id virtual void getSolutionPerDOFs(const ID & dof_id, Array<Real> & solution_array); private: /// Add a symmetric matrices to a symmetric sparse matrix inline void addSymmetricElementalMatrixToSymmetric( SparseMatrixAIJ & matrix, const Matrix<Real> & element_mat, const Vector<UInt> & equation_numbers, UInt max_size); /// Add a unsymmetric matrices to a symmetric sparse matrix (i.e. cohesive /// elements) inline void addUnsymmetricElementalMatrixToSymmetric( SparseMatrixAIJ & matrix, const Matrix<Real> & element_mat, const Vector<UInt> & equation_numbers, UInt max_size); /// Add a matrices to a unsymmetric sparse matrix inline void addElementalMatrixToUnsymmetric( SparseMatrixAIJ & matrix, const Matrix<Real> & element_mat, const Vector<UInt> & equation_numbers, UInt max_size); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// Get an instance of a new SparseMatrix virtual SparseMatrix & getNewMatrix(const ID & matrix_id, const MatrixType & matrix_type); /// Get an instance of a new SparseMatrix as a copy of the SparseMatrix /// matrix_to_copy_id virtual SparseMatrix & getNewMatrix(const ID & matrix_id, const ID & matrix_to_copy_id); /// Get the reference of an existing matrix SparseMatrixPETSc & getMatrix(const ID & matrix_id); /// Get the solution array AKANTU_GET_MACRO_NOT_CONST(GlobalSolution, this->solution, Vec &); /// Get the residual array AKANTU_GET_MACRO_NOT_CONST(Residual, this->residual, Vec &); /// Get the blocked dofs array // AKANTU_GET_MACRO(BlockedDOFs, blocked_dofs, const Array<bool> &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: typedef std::map<ID, SparseMatrixPETSc *> PETScMatrixMap; /// list of matrices registered to the dof manager PETScMatrixMap petsc_matrices; /// PETSc version of the solution Vec solution; /// PETSc version of the residual Vec residual; /// PETSc local to global mapping of dofs ISLocalToGlobalMapping is_ltog; /// Communicator associated to PETSc MPI_Comm mpi_communicator; /// Static handler for petsc to know if it was initialized or not static UInt petsc_dof_manager_instances; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DOF_MANAGER_PETSC_HH__ */ diff --git a/src/model/heat_transfer/heat_transfer_model.cc b/src/model/heat_transfer/heat_transfer_model.cc index 548b671ac..e77a516fd 100644 --- a/src/model/heat_transfer/heat_transfer_model.cc +++ b/src/model/heat_transfer/heat_transfer_model.cc @@ -1,1282 +1,1282 @@ /** * @file heat_transfer_model.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Srinivasa Babu Ramisetti <srinivasa.ramisetti@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Rui Wang <rui.wang@epfl.ch> * * @date creation: Sun May 01 2011 * @date last modification: Mon Nov 30 2015 * * @brief Implementation of HeatTransferModel class * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "heat_transfer_model.hh" #include "group_manager_inline_impl.cc" #include "dumpable_inline_impl.hh" #include "aka_math.hh" #include "aka_common.hh" #include "fe_engine_template.hh" #include "mesh.hh" #include "static_communicator.hh" #include "parser.hh" #include "generalized_trapezoidal.hh" #ifdef AKANTU_USE_MUMPS #include "solver_mumps.hh" #endif #ifdef AKANTU_USE_IOHELPER #include "dumper_paraview.hh" #include "dumper_elemental_field.hh" #include "dumper_element_partition.hh" #include "dumper_internal_material_field.hh" #endif /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { const HeatTransferModelOptions default_heat_transfer_model_options(_explicit_lumped_capacity); /* -------------------------------------------------------------------------- */ HeatTransferModel::HeatTransferModel(Mesh & mesh, UInt dim, const ID & id, const MemoryID & memory_id) : Model(mesh, dim, id, memory_id), Parsable(_st_heat, id), integrator(NULL), conductivity_matrix(NULL), capacity_matrix(NULL), jacobian_matrix(NULL), temperature_gradient("temperature_gradient", id), temperature_on_qpoints("temperature_on_qpoints", id), conductivity_on_qpoints("conductivity_on_qpoints", id), k_gradt_on_qpoints("k_gradt_on_qpoints", id), int_bt_k_gT("int_bt_k_gT", id), bt_k_gT("bt_k_gT", id), conductivity(spatial_dimension, spatial_dimension), thermal_energy("thermal_energy", id), solver(NULL), pbc_synch(NULL) { AKANTU_DEBUG_IN(); createSynchronizerRegistry(this); std::stringstream sstr; sstr << id << ":fem"; registerFEEngineObject<MyFEEngineType>(sstr.str(), mesh, spatial_dimension); this->temperature = NULL; this->residual = NULL; this->blocked_dofs = NULL; #ifdef AKANTU_USE_IOHELPER this->mesh.registerDumper<DumperParaview>("paraview_all", id, true); this->mesh.addDumpMesh(mesh, spatial_dimension, _not_ghost, _ek_regular); #endif this->registerParam("conductivity", conductivity, _pat_parsmod); this->registerParam("conductivity_variation", conductivity_variation, 0., _pat_parsmod); this->registerParam("temperature_reference", T_ref, 0., _pat_parsmod); this->registerParam("capacity", capacity, _pat_parsmod); this->registerParam("density", density, _pat_parsmod); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initModel() { getFEEngine().initShapeFunctions(_not_ghost); getFEEngine().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() { AKANTU_DEBUG_IN(); Model::initPBC(); pbc_synch = new PBCSynchronizer(pbc_pair); synch_registry->registerSynchronizer(*pbc_synch, _gst_htm_capacity); synch_registry->registerSynchronizer(*pbc_synch, _gst_htm_temperature); changeLocalEquationNumberForPBC(pbc_pair, 1); // as long as there are ones on the diagonal of the matrix, we can put // boudandary true for slaves std::map<UInt, UInt>::iterator it = pbc_pair.begin(); std::map<UInt, UInt>::iterator end = pbc_pair.end(); while (it != end) { (*blocked_dofs)((*it).first, 0) = true; ++it; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initArrays() { AKANTU_DEBUG_IN(); UInt nb_nodes = getFEEngine().getMesh().getNbNodes(); std::stringstream sstr_temp; sstr_temp << Model::id << ":temperature"; std::stringstream sstr_temp_rate; sstr_temp_rate << Model::id << ":temperature_rate"; std::stringstream sstr_inc; sstr_inc << Model::id << ":increment"; std::stringstream sstr_ext_flx; sstr_ext_flx << Model::id << ":external_flux"; std::stringstream sstr_residual; sstr_residual << Model::id << ":residual"; std::stringstream sstr_lump; sstr_lump << Model::id << ":lumped"; std::stringstream sstr_boun; sstr_boun << Model::id << ":blocked_dofs"; temperature = &(alloc<Real>(sstr_temp.str(), nb_nodes, 1, REAL_INIT_VALUE)); temperature_rate = &(alloc<Real>(sstr_temp_rate.str(), nb_nodes, 1, REAL_INIT_VALUE)); increment = &(alloc<Real>(sstr_inc.str(), nb_nodes, 1, REAL_INIT_VALUE)); external_heat_rate = &(alloc<Real>(sstr_ext_flx.str(), nb_nodes, 1, REAL_INIT_VALUE)); residual = &(alloc<Real>(sstr_residual.str(), nb_nodes, 1, REAL_INIT_VALUE)); capacity_lumped = &(alloc<Real>(sstr_lump.str(), nb_nodes, 1, REAL_INIT_VALUE)); blocked_dofs = &(alloc<bool>(sstr_boun.str(), nb_nodes, 1, false)); Mesh::ConnectivityTypeList::const_iterator it; /* -------------------------------------------------------------------------- */ // byelementtype vectors getFEEngine().getMesh().initElementTypeMapArray(temperature_on_qpoints, 1, spatial_dimension); getFEEngine().getMesh().initElementTypeMapArray( temperature_gradient, spatial_dimension, spatial_dimension); getFEEngine().getMesh().initElementTypeMapArray( conductivity_on_qpoints, spatial_dimension * spatial_dimension, spatial_dimension); getFEEngine().getMesh().initElementTypeMapArray( k_gradt_on_qpoints, spatial_dimension, spatial_dimension); getFEEngine().getMesh().initElementTypeMapArray(bt_k_gT, 1, spatial_dimension, true); getFEEngine().getMesh().initElementTypeMapArray(int_bt_k_gT, 1, spatial_dimension, true); getFEEngine().getMesh().initElementTypeMapArray(thermal_energy, 1, spatial_dimension); for (UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType)g; const Mesh::ConnectivityTypeList & type_list = getFEEngine().getMesh().getConnectivityTypeList(gt); for (it = type_list.begin(); it != type_list.end(); ++it) { if (Mesh::getSpatialDimension(*it) != spatial_dimension) continue; UInt nb_element = getFEEngine().getMesh().getNbElement(*it, gt); UInt nb_quad_points = this->getFEEngine().getNbIntegrationPoints(*it, gt) * nb_element; temperature_on_qpoints(*it, gt).resize(nb_quad_points); temperature_on_qpoints(*it, gt).clear(); temperature_gradient(*it, gt).resize(nb_quad_points); temperature_gradient(*it, gt).clear(); conductivity_on_qpoints(*it, gt).resize(nb_quad_points); conductivity_on_qpoints(*it, gt).clear(); k_gradt_on_qpoints(*it, gt).resize(nb_quad_points); k_gradt_on_qpoints(*it, gt).clear(); bt_k_gT(*it, gt).resize(nb_quad_points); bt_k_gT(*it, gt).clear(); int_bt_k_gT(*it, gt).resize(nb_element); int_bt_k_gT(*it, gt).clear(); thermal_energy(*it, gt).resize(nb_element); thermal_energy(*it, gt).clear(); } } /* -------------------------------------------------------------------------- */ dof_synchronizer = new DOFSynchronizer(getFEEngine().getMesh(), 1); dof_synchronizer->initLocalDOFEquationNumbers(); dof_synchronizer->initGlobalDOFEquationNumbers(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initSolver(__attribute__((unused)) SolverOptions & options) { #if !defined(AKANTU_USE_MUMPS) // or other solver in the future \todo add // AKANTU_HAS_SOLVER in CMake AKANTU_DEBUG_ERROR("You should at least activate one solver."); #else UInt nb_global_nodes = mesh.getNbGlobalNodes(); delete jacobian_matrix; std::stringstream sstr; sstr << Memory::id << ":jacobian_matrix"; jacobian_matrix = new SparseMatrix(nb_global_nodes, _symmetric, sstr.str(), memory_id); jacobian_matrix->buildProfile(mesh, *dof_synchronizer, 1); delete conductivity_matrix; std::stringstream sstr_sti; sstr_sti << Memory::id << ":conductivity_matrix"; conductivity_matrix = new SparseMatrix(*jacobian_matrix, sstr_sti.str(), memory_id); #ifdef AKANTU_USE_MUMPS std::stringstream sstr_solv; sstr_solv << Memory::id << ":solver"; solver = new SolverMumps(*jacobian_matrix, sstr_solv.str()); dof_synchronizer->initScatterGatherCommunicationScheme(); #else AKANTU_DEBUG_ERROR("You should at least activate one solver."); #endif // AKANTU_USE_MUMPS if (solver) solver->initialize(options); #endif // AKANTU_HAS_SOLVER } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initImplicit(bool dynamic, SolverOptions & solver_options) { AKANTU_DEBUG_IN(); method = dynamic ? _implicit_dynamic : _static; initSolver(solver_options); if (method == _implicit_dynamic) { if (integrator) delete integrator; integrator = new TrapezoidalRule1(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ HeatTransferModel::~HeatTransferModel() { AKANTU_DEBUG_IN(); if (integrator) delete integrator; if (conductivity_matrix) delete conductivity_matrix; if (capacity_matrix) delete capacity_matrix; if (jacobian_matrix) delete jacobian_matrix; if (solver) delete solver; delete pbc_synch; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::assembleCapacityLumped(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); FEEngine & fem = getFEEngine(); 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 = getFEEngine().getMesh().getNbElement(*it, ghost_type); UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(*it, ghost_type); Array<Real> 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(_gst_htm_capacity); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::updateResidual( __attribute__((unused)) bool compute_conductivity) { 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(); residual->copy(*external_heat_rate); /// then @f$ r -= q_{int} @f$ // update the not ghost ones updateResidual(_not_ghost); // update for the received ghosts updateResidual(_ghost); /* if (method == _explicit_lumped_capacity) { this->solveExplicitLumped(); }*/ AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::assembleConductivityMatrix(bool compute_conductivity) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Assemble the new stiffness matrix."); conductivity_matrix->clear(); switch (mesh.getSpatialDimension()) { case 1: this->assembleConductivityMatrix<1>(_not_ghost, compute_conductivity); break; case 2: this->assembleConductivityMatrix<2>(_not_ghost, compute_conductivity); break; case 3: this->assembleConductivityMatrix<3>(_not_ghost, compute_conductivity); break; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void HeatTransferModel::assembleConductivityMatrix(const GhostType & ghost_type, bool compute_conductivity) { AKANTU_DEBUG_IN(); Mesh & mesh = this->getFEEngine().getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type); for (; it != last_type; ++it) { this->assembleConductivityMatrix<dim>(*it, ghost_type, compute_conductivity); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template <UInt dim> void HeatTransferModel::assembleConductivityMatrix(const ElementType & type, const GhostType & ghost_type, bool compute_conductivity) { AKANTU_DEBUG_IN(); SparseMatrix & K = *conductivity_matrix; const Array<Real> & shapes_derivatives = this->getFEEngine().getShapesDerivatives(type, ghost_type); UInt nb_element = mesh.getNbElement(type, ghost_type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(type, ghost_type); /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ UInt bt_d_b_size = nb_nodes_per_element; Array<Real> * bt_d_b = new Array<Real>(nb_element * nb_quadrature_points, bt_d_b_size * bt_d_b_size, "B^t*D*B"); Matrix<Real> Bt_D(nb_nodes_per_element, dim); Array<Real>::const_iterator<Matrix<Real> > shapes_derivatives_it = shapes_derivatives.begin(dim, nb_nodes_per_element); Array<Real>::iterator<Matrix<Real> > Bt_D_B_it = bt_d_b->begin(bt_d_b_size, bt_d_b_size); if (compute_conductivity) this->computeConductivityOnQuadPoints(ghost_type); Array<Real>::iterator<Matrix<Real> > D_it = conductivity_on_qpoints(type, ghost_type).begin(dim, dim); Array<Real>::iterator<Matrix<Real> > D_end = conductivity_on_qpoints(type, ghost_type).end(dim, dim); for (; D_it != D_end; ++D_it, ++Bt_D_B_it, ++shapes_derivatives_it) { Matrix<Real> & D = *D_it; const Matrix<Real> & B = *shapes_derivatives_it; Matrix<Real> & Bt_D_B = *Bt_D_B_it; Bt_D.mul<true, false>(B, D); Bt_D_B.mul<false, false>(Bt_D, B); } /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Array<Real> * K_e = new Array<Real>(nb_element, bt_d_b_size * bt_d_b_size, "K_e"); this->getFEEngine().integrate(*bt_d_b, *K_e, bt_d_b_size * bt_d_b_size, type, ghost_type); delete bt_d_b; this->getFEEngine().assembleMatrix(*K_e, K, 1, type, ghost_type); delete K_e; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::updateResidualInternal() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Update the residual"); // f = q_ext - q_int - Mddot = q - Mddot; if (method != _static) { // f -= Mddot if (capacity_matrix) { // if full mass_matrix Array<Real> * Mddot = new Array<Real>(*temperature_rate, true, "Mddot"); *Mddot *= *capacity_matrix; *residual -= *Mddot; delete Mddot; } else if (capacity_lumped) { // else lumped mass UInt nb_nodes = temperature_rate->getSize(); UInt nb_degree_of_freedom = temperature_rate->getNbComponent(); Real * capacity_val = capacity_lumped->storage(); Real * temp_rate_val = temperature_rate->storage(); Real * res_val = residual->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) { if (!(*blocked_dofs_val)) { *res_val -= *temp_rate_val ** capacity_val; } blocked_dofs_val++; res_val++; capacity_val++; temp_rate_val++; } } else { AKANTU_DEBUG_ERROR("No function called to assemble the mass matrix."); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::solveStatic() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Solving Ku = f"); AKANTU_DEBUG_ASSERT(conductivity_matrix != NULL, "You should first initialize the implicit solver and " "assemble the stiffness matrix"); UInt nb_nodes = temperature->getSize(); UInt nb_degree_of_freedom = temperature->getNbComponent() * nb_nodes; jacobian_matrix->copyContent(*conductivity_matrix); jacobian_matrix->applyBoundary(*blocked_dofs); increment->clear(); solver->setRHS(*residual); solver->factorize(); solver->solve(*increment); Real * increment_val = increment->storage(); Real * temperature_val = temperature->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); for (UInt j = 0; j < nb_degree_of_freedom; ++j, ++temperature_val, ++increment_val, ++blocked_dofs_val) { if (!(*blocked_dofs_val)) { *temperature_val += *increment_val; } else { *increment_val = 0.0; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::computeConductivityOnQuadPoints( const GhostType & ghost_type) { const Mesh::ConnectivityTypeList & type_list = this->getFEEngine().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; Array<Real> & temperature_interpolated = temperature_on_qpoints(*it, ghost_type); // compute the temperature on quadrature points this->getFEEngine().interpolateOnIntegrationPoints( *temperature, temperature_interpolated, 1, *it, ghost_type); Array<Real>::matrix_iterator C_it = conductivity_on_qpoints(*it, ghost_type) .begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator C_end = conductivity_on_qpoints(*it, ghost_type) .end(spatial_dimension, spatial_dimension); Array<Real>::iterator<Real> T_it = temperature_interpolated.begin(); for (; C_it != C_end; ++C_it, ++T_it) { Matrix<Real> & C = *C_it; Real & T = *T_it; C = conductivity; Matrix<Real> variation(spatial_dimension, spatial_dimension, conductivity_variation * (T - T_ref)); C += conductivity_variation; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::computeKgradT(const GhostType & ghost_type, bool compute_conductivity) { if (compute_conductivity) computeConductivityOnQuadPoints(ghost_type); const Mesh::ConnectivityTypeList & type_list = this->getFEEngine().getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for (it = type_list.begin(); it != type_list.end(); ++it) { const ElementType & type = *it; if (Mesh::getSpatialDimension(*it) != spatial_dimension) continue; Array<Real> & gradient = temperature_gradient(*it, ghost_type); this->getFEEngine().gradientOnIntegrationPoints(*temperature, gradient, 1, *it, ghost_type); Array<Real>::matrix_iterator C_it = conductivity_on_qpoints(*it, ghost_type) .begin(spatial_dimension, spatial_dimension); Array<Real>::vector_iterator BT_it = gradient.begin(spatial_dimension); Array<Real>::vector_iterator k_BT_it = k_gradt_on_qpoints(type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator k_BT_end = k_gradt_on_qpoints(type, ghost_type).end(spatial_dimension); for (; k_BT_it != k_BT_end; ++k_BT_it, ++BT_it, ++C_it) { Vector<Real> & k_BT = *k_BT_it; Vector<Real> & BT = *BT_it; Matrix<Real> & C = *C_it; k_BT.mul<false>(C, BT); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::updateResidual(const GhostType & ghost_type, bool compute_conductivity) { AKANTU_DEBUG_IN(); const Mesh::ConnectivityTypeList & type_list = this->getFEEngine().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; Array<Real> & shapes_derivatives = const_cast<Array<Real> &>( getFEEngine().getShapesDerivatives(*it, ghost_type)); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); // compute k \grad T computeKgradT(ghost_type, compute_conductivity); Array<Real>::vector_iterator k_BT_it = k_gradt_on_qpoints(*it, ghost_type).begin(spatial_dimension); Array<Real>::matrix_iterator B_it = shapes_derivatives.begin(spatial_dimension, nb_nodes_per_element); Array<Real>::vector_iterator Bt_k_BT_it = bt_k_gT(*it, ghost_type).begin(nb_nodes_per_element); Array<Real>::vector_iterator Bt_k_BT_end = bt_k_gT(*it, ghost_type).end(nb_nodes_per_element); for (; Bt_k_BT_it != Bt_k_BT_end; ++Bt_k_BT_it, ++B_it, ++k_BT_it) { Vector<Real> & k_BT = *k_BT_it; Vector<Real> & Bt_k_BT = *Bt_k_BT_it; Matrix<Real> & B = *B_it; Bt_k_BT.mul<true>(B, k_BT); } this->getFEEngine().integrate(bt_k_gT(*it, ghost_type), int_bt_k_gT(*it, ghost_type), nb_nodes_per_element, *it, ghost_type); this->getFEEngine().assembleArray( int_bt_k_gT(*it, ghost_type), *residual, dof_synchronizer->getLocalDOFEquationNumbers(), 1, *it, ghost_type, empty_filter, -1); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::solveExplicitLumped() { AKANTU_DEBUG_IN(); /// finally @f$ r -= C \dot T @f$ // lumped C UInt nb_nodes = temperature_rate->getSize(); UInt nb_degree_of_freedom = temperature_rate->getNbComponent(); Real * capacity_val = capacity_lumped->storage(); Real * temp_rate_val = temperature_rate->storage(); Real * res_val = residual->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) { if (!(*blocked_dofs_val)) { *res_val -= *capacity_val ** temp_rate_val; } blocked_dofs_val++; res_val++; capacity_val++; temp_rate_val++; } #ifndef AKANTU_NDEBUG getSynchronizerRegistry().synchronize(akantu::_gst_htm_gradient_temperature); #endif capacity_val = capacity_lumped->storage(); res_val = residual->storage(); blocked_dofs_val = blocked_dofs->storage(); Real * inc = increment->storage(); for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) { if (!(*blocked_dofs_val)) { *inc = (*res_val / *capacity_val); } res_val++; blocked_dofs_val++; inc++; capacity_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::explicitPred() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(integrator, "integrator was not instanciated"); integrator->integrationSchemePred(time_step, *temperature, *temperature_rate, *blocked_dofs); UInt nb_nodes = temperature->getSize(); UInt nb_degree_of_freedom = temperature->getNbComponent(); Real * temp = temperature->storage(); for (UInt n = 0; n < nb_nodes * nb_degree_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, *blocked_dofs, *increment); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::implicitPred() { AKANTU_DEBUG_IN(); if (method == _implicit_dynamic) integrator->integrationSchemePred(time_step, *temperature, *temperature_rate, *blocked_dofs); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::implicitCorr() { AKANTU_DEBUG_IN(); if (method == _implicit_dynamic) { integrator->integrationSchemeCorrTemp( time_step, *temperature, *temperature_rate, *blocked_dofs, *increment); } else { UInt nb_nodes = temperature->getSize(); UInt nb_degree_of_freedom = temperature->getNbComponent() * nb_nodes; Real * incr_val = increment->storage(); Real * temp_val = temperature->storage(); bool * boun_val = blocked_dofs->storage(); for (UInt j = 0; j < nb_degree_of_freedom; ++j, ++temp_val, ++incr_val, ++boun_val) { *incr_val *= (1. - *boun_val); *temp_val += *incr_val; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getStableTimeStep() { AKANTU_DEBUG_IN(); Real el_size; Real min_el_size = std::numeric_limits<Real>::max(); Real conductivitymax = conductivity(0, 0); // get the biggest parameter from k11 until k33// for (UInt i = 0; i < spatial_dimension; i++) for (UInt j = 0; j < spatial_dimension; j++) conductivitymax = std::max(conductivity(i, j), conductivitymax); const Mesh::ConnectivityTypeList & type_list = getFEEngine().getMesh().getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for (it = type_list.begin(); it != type_list.end(); ++it) { if (getFEEngine().getMesh().getSpatialDimension(*it) != spatial_dimension) continue; UInt nb_nodes_per_element = getFEEngine().getMesh().getNbNodesPerElement(*it); Array<Real> coord(0, nb_nodes_per_element * spatial_dimension); FEEngine::extractNodalToElementField(getFEEngine().getMesh(), getFEEngine().getMesh().getNodes(), coord, *it, _not_ghost); Array<Real>::matrix_iterator el_coord = coord.begin(spatial_dimension, nb_nodes_per_element); UInt nb_element = getFEEngine().getMesh().getNbElement(*it); for (UInt el = 0; el < nb_element; ++el, ++el_coord) { el_size = getFEEngine().getElementInradius(*el_coord, *it); 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); } 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() { std::pair<Parser::const_section_iterator, Parser::const_section_iterator> sub_sect = this->parser->getSubSections(_st_heat); Parser::const_section_iterator it = sub_sect.first; const ParserSection & section = *it; this->parseSection(section); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initFull(const ModelOptions & options) { Model::initFull(options); readMaterials(); const HeatTransferModelOptions & my_options = dynamic_cast<const HeatTransferModelOptions &>(options); method = my_options.analysis_method; // initialize the vectors initArrays(); temperature->clear(); temperature_rate->clear(); external_heat_rate->clear(); // initialize pbc if (pbc_pair.size() != 0) initPBC(); if (method == _explicit_lumped_capacity) { integrator = new ForwardEuler(); } if (method == _implicit_dynamic) { initImplicit(true); } if (method == _static) { initImplicit(false); } } /* -------------------------------------------------------------------------- */ void HeatTransferModel::assembleCapacity() { AKANTU_DEBUG_IN(); if (!capacity_matrix) { std::stringstream sstr; sstr << id << ":capacity_matrix"; capacity_matrix = new SparseMatrix(*jacobian_matrix, sstr.str(), memory_id); } assembleCapacity(_not_ghost); // assembleMass(_ghost); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ class ComputeRhoFunctor { public: ComputeRhoFunctor(const HeatTransferModel & model) : model(model){}; void operator()(Matrix<Real> & rho, const Element &, const Matrix<Real> &) const { rho.set(model.getCapacity()); } private: const HeatTransferModel & model; }; /* -------------------------------------------------------------------------- */ void HeatTransferModel::assembleCapacity(GhostType ghost_type) { AKANTU_DEBUG_IN(); MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>(); ComputeRhoFunctor rho_functor(*this); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type); for (; it != end; ++it) { ElementType type = *it; fem.assembleFieldMatrix(rho_functor, 1, *capacity_matrix, type, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::computeRho(Array<Real> & rho, ElementType type, GhostType ghost_type) { AKANTU_DEBUG_IN(); FEEngine & fem = this->getFEEngine(); UInt nb_element = fem.getMesh().getNbElement(type, ghost_type); UInt nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type); rho.resize(nb_element * nb_quadrature_points); Real * rho_1_val = rho.storage(); /// compute @f$ rho @f$ for each nodes of each element for (UInt el = 0; el < nb_element; ++el) { for (UInt n = 0; n < nb_quadrature_points; ++n) { *rho_1_val++ = this->capacity; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> bool HeatTransferModel::testConvergence<_scc_increment>(Real tolerance, Real & error) { AKANTU_DEBUG_IN(); UInt nb_nodes = temperature->getSize(); UInt nb_degree_of_freedom = temperature->getNbComponent(); error = 0; Real norm[2] = {0., 0.}; Real * increment_val = increment->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); Real * temperature_val = temperature->storage(); for (UInt n = 0; n < nb_nodes; ++n) { bool is_local_node = mesh.isLocalOrMasterNode(n); for (UInt d = 0; d < nb_degree_of_freedom; ++d) { if (!(*blocked_dofs_val) && is_local_node) { norm[0] += *increment_val * *increment_val; norm[1] += *temperature_val * *temperature_val; } blocked_dofs_val++; increment_val++; temperature_val++; } } StaticCommunicator::getStaticCommunicator().allReduce(norm, 2, _so_sum); norm[0] = sqrt(norm[0]); norm[1] = sqrt(norm[1]); AKANTU_DEBUG_ASSERT(!Math::isnan(norm[0]), "Something goes wrong in the solve phase"); if (norm[1] < Math::getTolerance()) { error = norm[0]; AKANTU_DEBUG_OUT(); // cout<<"Error 1: "<<error<<endl; return error < tolerance; } AKANTU_DEBUG_OUT(); if (norm[1] > Math::getTolerance()) error = norm[0] / norm[1]; else error = norm[0]; // In case the total displacement is zero! // cout<<"Error 2: "<<error<<endl; return (error < tolerance); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initFEEngineBoundary(bool create_surface) { if (create_surface) MeshUtils::buildFacets(getFEEngine().getMesh()); FEEngine & fem_boundary = getFEEngineBoundary(); fem_boundary.initShapeFunctions(); fem_boundary.computeNormalsOnIntegrationPoints(); } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::computeThermalEnergyByNode() { AKANTU_DEBUG_IN(); Real ethermal = 0.; Array<Real>::vector_iterator heat_rate_it = residual->begin(residual->getNbComponent()); Array<Real>::vector_iterator heat_rate_end = residual->end(residual->getNbComponent()); UInt n = 0; for (; heat_rate_it != heat_rate_end; ++heat_rate_it, ++n) { Real heat = 0; bool is_local_node = mesh.isLocalOrMasterNode(n); bool is_not_pbc_slave_node = !isPBCSlaveNode(n); bool count_node = is_local_node && is_not_pbc_slave_node; Vector<Real> & heat_rate = *heat_rate_it; for (UInt i = 0; i < heat_rate.size(); ++i) { if (count_node) heat += heat_rate[i] * time_step; } ethermal += heat; } StaticCommunicator::getStaticCommunicator().allReduce(ðermal, 1, _so_sum); AKANTU_DEBUG_OUT(); return ethermal; } /* -------------------------------------------------------------------------- */ template <class iterator> void HeatTransferModel::getThermalEnergy( iterator Eth, Array<Real>::const_iterator<Real> T_it, Array<Real>::const_iterator<Real> T_end) const { for (; T_it != T_end; ++T_it, ++Eth) { *Eth = capacity * density ** T_it; } } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getThermalEnergy(const ElementType & type, UInt index) { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(type); Vector<Real> Eth_on_quarature_points(nb_quadrature_points); Array<Real>::iterator<Real> T_it = this->temperature_on_qpoints(type).begin(); T_it += index * nb_quadrature_points; Array<Real>::iterator<Real> T_end = T_it + nb_quadrature_points; getThermalEnergy(Eth_on_quarature_points.storage(), T_it, T_end); return getFEEngine().integrate(Eth_on_quarature_points, type, index); } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getThermalEnergy() { Real Eth = 0; Mesh & mesh = getFEEngine().getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension); for (; it != last_type; ++it) { UInt nb_element = getFEEngine().getMesh().getNbElement(*it, _not_ghost); UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(*it, _not_ghost); Array<Real> Eth_per_quad(nb_element * nb_quadrature_points, 1); Array<Real>::iterator<Real> T_it = this->temperature_on_qpoints(*it).begin(); Array<Real>::iterator<Real> T_end = this->temperature_on_qpoints(*it).end(); getThermalEnergy(Eth_per_quad.begin(), T_it, T_end); Eth += getFEEngine().integrate(Eth_per_quad, *it); } return Eth; } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getEnergy(const std::string & id) { AKANTU_DEBUG_IN(); Real energy = 0; if (id == "thermal") energy = getThermalEnergy(); // reduction sum over all processors StaticCommunicator::getStaticCommunicator().allReduce(&energy, 1, _so_sum); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getEnergy(const std::string & id, const ElementType & type, UInt index) { AKANTU_DEBUG_IN(); Real energy = 0.; if (id == "thermal") energy = getThermalEnergy(type, index); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER dumper::Field * HeatTransferModel::createNodalFieldBool( const std::string & field_name, const std::string & group_name, __attribute__((unused)) bool padding_flag) { std::map<std::string, Array<bool> *> uint_nodal_fields; uint_nodal_fields["blocked_dofs"] = blocked_dofs; dumper::Field * field = NULL; field = mesh.createNodalField(uint_nodal_fields[field_name], group_name); return field; } /* -------------------------------------------------------------------------- */ dumper::Field * HeatTransferModel::createNodalFieldReal( const std::string & field_name, const std::string & group_name, __attribute__((unused)) bool padding_flag) { std::map<std::string, Array<Real> *> real_nodal_fields; real_nodal_fields["temperature"] = temperature; real_nodal_fields["temperature_rate"] = temperature_rate; real_nodal_fields["external_heat_rate"] = external_heat_rate; real_nodal_fields["residual"] = residual; real_nodal_fields["capacity_lumped"] = capacity_lumped; real_nodal_fields["increment"] = increment; dumper::Field * field = mesh.createNodalField(real_nodal_fields[field_name], group_name); return field; } /* -------------------------------------------------------------------------- */ dumper::Field * HeatTransferModel::createElementalField( const std::string & field_name, const std::string & group_name, __attribute__((unused)) bool padding_flag, __attribute__((unused)) const UInt & spatial_dimension, const ElementKind & element_kind) { dumper::Field * field = NULL; if (field_name == "partitions") field = mesh.createElementalField<UInt, dumper::ElementPartitionField>( mesh.getConnectivities(), group_name, this->spatial_dimension, element_kind); else if (field_name == "temperature_gradient") { ElementTypeMap<UInt> nb_data_per_elem = this->mesh.getNbDataPerElem(temperature_gradient, element_kind); field = mesh.createElementalField<Real, dumper::InternalMaterialField>( temperature_gradient, group_name, this->spatial_dimension, element_kind, nb_data_per_elem); } else if (field_name == "conductivity") { ElementTypeMap<UInt> nb_data_per_elem = this->mesh.getNbDataPerElem(conductivity_on_qpoints, element_kind); field = mesh.createElementalField<Real, dumper::InternalMaterialField>( conductivity_on_qpoints, group_name, this->spatial_dimension, element_kind, nb_data_per_elem); } return field; } /* -------------------------------------------------------------------------- */ #else /* -------------------------------------------------------------------------- */ dumper::Field * HeatTransferModel::createElementalField( __attribute__((unused)) const std::string & field_name, __attribute__((unused)) const std::string & group_name, __attribute__((unused)) bool padding_flag, __attribute__((unused)) const ElementKind & element_kind) { return NULL; } /* -------------------------------------------------------------------------- */ dumper::Field * HeatTransferModel::createNodalFieldBool( __attribute__((unused)) const std::string & field_name, __attribute__((unused)) const std::string & group_name, __attribute__((unused)) bool padding_flag) { return NULL; } /* -------------------------------------------------------------------------- */ dumper::Field * HeatTransferModel::createNodalFieldReal( __attribute__((unused)) const std::string & field_name, __attribute__((unused)) const std::string & group_name, __attribute__((unused)) bool padding_flag) { return NULL; } #endif -__END_AKANTU__ +} // akantu diff --git a/src/model/heat_transfer/heat_transfer_model.hh b/src/model/heat_transfer/heat_transfer_model.hh index c32e85634..0826bebb4 100644 --- a/src/model/heat_transfer/heat_transfer_model.hh +++ b/src/model/heat_transfer/heat_transfer_model.hh @@ -1,456 +1,456 @@ /** * @file heat_transfer_model.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Srinivasa Babu Ramisetti <srinivasa.ramisetti@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Rui Wang <rui.wang@epfl.ch> * * @date creation: Sun May 01 2011 * @date last modification: Tue Dec 08 2015 * * @brief Model of Heat Transfer * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_HEAT_TRANSFER_MODEL_HH__ #define __AKANTU_HEAT_TRANSFER_MODEL_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_types.hh" #include "aka_voigthelper.hh" #include "aka_memory.hh" #include "model.hh" #include "integrator_gauss.hh" #include "shape_lagrange.hh" #include "dumpable.hh" #include "parsable.hh" #include "solver.hh" #include "generalized_trapezoidal.hh" namespace akantu { class IntegrationScheme1stOrder; } -__BEGIN_AKANTU__ +namespace akantu { struct HeatTransferModelOptions : public ModelOptions { HeatTransferModelOptions(AnalysisMethod analysis_method = _explicit_lumped_capacity ) : analysis_method(analysis_method) {} AnalysisMethod analysis_method; }; extern const HeatTransferModelOptions default_heat_transfer_model_options; class HeatTransferModel : public Model, public DataAccessor, public Parsable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef FEEngineTemplate<IntegratorGauss,ShapeLagrange> MyFEEngineType; HeatTransferModel(Mesh & mesh, UInt spatial_dimension = _all_dimensions, const ID & id = "heat_transfer_model", const MemoryID & memory_id = 0); virtual ~HeatTransferModel() ; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// generic function to initialize everything ready for explicit dynamics void initFull(const ModelOptions & options = default_heat_transfer_model_options); /// initialize the fem object of the boundary void initFEEngineBoundary(bool create_surface = true); /// read one material file to instantiate all the materials void readMaterials(); /// allocate all vectors void initArrays(); /// 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(); /// initialize the solver and the jacobian_matrix (called by initImplicit) void initSolver(SolverOptions & solver_options); /// initialize the stuff for the implicit solver void initImplicit(bool dynamic, SolverOptions & solver_options = _solver_no_options); /// function to print the contain of the class virtual void printself(__attribute__ ((unused)) std::ostream & stream, __attribute__ ((unused)) int indent = 0) const {}; /* ------------------------------------------------------------------------ */ /* Methods for explicit */ /* ------------------------------------------------------------------------ */ public: /// compute and get the stable time step Real getStableTimeStep(); /// compute the heat flux void updateResidual(bool compute_conductivity = false); /// 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(); /// implicit time integration predictor void implicitPred(); /// implicit time integration corrector void implicitCorr(); /// solve the system in temperature rate @f$C\delta \dot T = q_{n+1} - C \dot T_{n}@f$ /// this function needs to be run for dynamics void solveExplicitLumped(); // /// initialize the heat flux // void initializeResidual(Array<Real> &temp); // /// initialize temperature // void initializeTemperature(Array<Real> &temp); /* ------------------------------------------------------------------------ */ /* Methods for implicit */ /* ------------------------------------------------------------------------ */ public: /** * solve Kt = q **/ void solveStatic(); /// test if the system is converged template <SolveConvergenceCriteria criteria> bool testConvergence(Real tolerance, Real & error); /** * solve a step (predictor + convergence loop + corrector) using the * the given convergence method (see akantu::SolveConvergenceMethod) * and the given convergence criteria (see * akantu::SolveConvergenceCriteria) **/ template <SolveConvergenceMethod method, SolveConvergenceCriteria criteria> bool solveStep(Real tolerance, UInt max_iteration = 100); template <SolveConvergenceMethod method, SolveConvergenceCriteria criteria> bool solveStep(Real tolerance, Real & error, UInt max_iteration = 100, bool do_not_factorize = false); /// assemble the conductivity matrix void assembleConductivityMatrix(bool compute_conductivity = true); /// assemble the conductivity matrix void assembleCapacity(); /// assemble the conductivity matrix void assembleCapacity(GhostType ghost_type); /// compute the capacity on quadrature points void computeRho(Array<Real> & rho, ElementType type, GhostType ghost_type); protected: /// compute A and solve @f[ A\delta u = f_ext - f_int @f] template <GeneralizedTrapezoidal::IntegrationSchemeCorrectorType type> void solve(Array<Real> &increment, Real block_val = 1., bool need_factorize = true, bool has_profile_changed = false); /// computation of the residual for the convergence loop void updateResidualInternal(); private: /// compute the heat flux on ghost types void updateResidual(const GhostType & ghost_type, bool compute_conductivity = false); /// calculate the lumped capacity vector for heat transfer problem (w ghosttype) void assembleCapacityLumped(const GhostType & ghost_type); /// assemble the conductivity matrix (w/ ghost type) template <UInt dim> void assembleConductivityMatrix(const GhostType & ghost_type, bool compute_conductivity = true); /// assemble the conductivity matrix template <UInt dim> void assembleConductivityMatrix(const ElementType & type, const GhostType & ghost_type, bool compute_conductivity = true); /// compute the conductivity tensor for each quadrature point in an array void computeConductivityOnQuadPoints(const GhostType & ghost_type); /// compute vector k \grad T for each quadrature point void computeKgradT(const GhostType & ghost_type,bool compute_conductivity); /// compute the thermal energy Real computeThermalEnergyByNode(); /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ public: inline UInt getNbDataForElements(const Array<Element> & elements, SynchronizationTag tag) const; inline void packElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag) const; inline void unpackElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag); 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); /* ------------------------------------------------------------------------ */ /* Dumpable interface */ /* ------------------------------------------------------------------------ */ public: virtual dumper::Field * createNodalFieldReal(const std::string & field_name, const std::string & group_name, bool padding_flag); virtual dumper::Field * createNodalFieldBool(const std::string & field_name, const std::string & group_name, bool padding_flag); virtual dumper::Field * createElementalField(const std::string & field_name, const std::string & group_name, bool padding_flag, const UInt & spatial_dimension, const ElementKind & kind); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: inline FEEngine & getFEEngineBoundary(const std::string & name = ""); AKANTU_GET_MACRO(Density, density, Real); AKANTU_GET_MACRO(Capacity, capacity, Real); /// 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, Array<Real>&); /// get the lumped capacity AKANTU_GET_MACRO(CapacityLumped, *capacity_lumped, Array<Real>&); /// get the boundary vector AKANTU_GET_MACRO(BlockedDOFs, *blocked_dofs, Array<bool>&); /// get conductivity matrix AKANTU_GET_MACRO(ConductivityMatrix, *conductivity_matrix, const SparseMatrix&); /// get the external heat rate vector AKANTU_GET_MACRO(ExternalHeatRate, *external_heat_rate, Array<Real>&); /// get the temperature gradient AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(TemperatureGradient, temperature_gradient, Real); /// get the conductivity on q points AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ConductivityOnQpoints, conductivity_on_qpoints, Real); /// get the conductivity on q points AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(TemperatureOnQpoints, temperature_on_qpoints, Real); /// internal variables AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(KGradtOnQpoints, k_gradt_on_qpoints, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(IntBtKgT, int_bt_k_gT, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(BtKgT, bt_k_gT, Real); /// get the temperature AKANTU_GET_MACRO(Temperature, *temperature, Array<Real> &); /// get the temperature derivative AKANTU_GET_MACRO(TemperatureRate, *temperature_rate, Array<Real> &); /// get the equation number Array<Int> AKANTU_GET_MACRO(EquationNumber, *equation_number, const Array<Int> &); /// get the energy denominated by thermal Real getEnergy(const std::string & energy_id, const ElementType & type, UInt index); /// get the energy denominated by thermal Real getEnergy(const std::string & energy_id); /// get the thermal energy for a given element Real getThermalEnergy(const ElementType & type, UInt index); /// get the thermal energy for a given element Real getThermalEnergy(); protected: /* ----------------------------------------------------------------------- */ template<class iterator> void getThermalEnergy(iterator Eth, Array<Real>::const_iterator<Real> T_it, Array<Real>::const_iterator<Real> T_end) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// number of iterations UInt n_iter; IntegrationScheme1stOrder * integrator; /// time step Real time_step; /// temperatures array Array<Real> * temperature; /// temperatures derivatives array Array<Real> * temperature_rate; /// increment array (@f$\delta \dot T@f$ or @f$\delta T@f$) Array<Real> * increment; /// conductivity matrix SparseMatrix * conductivity_matrix; /// capacity matrix SparseMatrix *capacity_matrix; /// jacobian matrix SparseMatrix * jacobian_matrix; /// the density Real density; /// the speed of the changing temperature ElementTypeMapArray<Real> temperature_gradient; /// temperature field on quadrature points ElementTypeMapArray<Real> temperature_on_qpoints; /// conductivity tensor on quadrature points ElementTypeMapArray<Real> conductivity_on_qpoints; /// vector k \grad T on quad points ElementTypeMapArray<Real> k_gradt_on_qpoints; /// vector \int \grad N k \grad T ElementTypeMapArray<Real> int_bt_k_gT; /// vector \grad N k \grad T ElementTypeMapArray<Real> bt_k_gT; /// external flux vector Array<Real> * external_heat_rate; /// residuals array Array<Real> * residual; /// position of a dof in the K matrix Array<Int> * equation_number; //lumped vector Array<Real> * capacity_lumped; /// boundary vector Array<bool> * blocked_dofs; //realtime Real time; ///capacity Real capacity; //conductivity matrix Matrix<Real> conductivity; //linear variation of the conductivity (for temperature dependent conductivity) Real conductivity_variation; // reference temperature for the interpretation of temperature variation Real T_ref; //the biggest parameter of conductivity matrix Real conductivitymax; /// thermal energy by element ElementTypeMapArray<Real> thermal_energy; /// Solver Solver * solver; /// analysis method AnalysisMethod method; /// pointer to the pbc synchronizer PBCSynchronizer * pbc_synch; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "heat_transfer_model_inline_impl.cc" #endif /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const HeatTransferModel & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_HEAT_TRANSFER_MODEL_HH__ */ diff --git a/src/model/integration_scheme/generalized_trapezoidal.cc b/src/model/integration_scheme/generalized_trapezoidal.cc index cef1e7214..5ef035f12 100644 --- a/src/model/integration_scheme/generalized_trapezoidal.cc +++ b/src/model/integration_scheme/generalized_trapezoidal.cc @@ -1,192 +1,192 @@ /** * @file generalized_trapezoidal.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Jul 04 2011 * @date last modification: Thu Jun 05 2014 * * @brief implementation of inline functions * * @section LICENSE * * Copyright (©) 2010-2012, 2014 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "generalized_trapezoidal.hh" #include "mesh.hh" #include "aka_array.hh" #include "dof_manager.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ GeneralizedTrapezoidal::GeneralizedTrapezoidal(DOFManager & dof_manager, const ID & dof_id, Real alpha) : IntegrationScheme1stOrder(dof_manager, dof_id), alpha(alpha) { this->registerParam("alpha", this->alpha, alpha, _pat_parsmod, "The alpha parameter"); } /* -------------------------------------------------------------------------- */ void GeneralizedTrapezoidal::predictor(Real delta_t, Array<Real> & u, Array<Real> & u_dot, const Array<bool> & blocked_dofs) const { AKANTU_DEBUG_IN(); UInt nb_nodes = u.getSize(); UInt nb_degree_of_freedom = u.getNbComponent() * nb_nodes; Real * u_val = u.storage(); Real * u_dot_val = u_dot.storage(); bool * blocked_dofs_val = blocked_dofs.storage(); for (UInt d = 0; d < nb_degree_of_freedom; d++) { if (!(*blocked_dofs_val)) { *u_val += (1. - alpha) * delta_t * *u_dot_val; } u_val++; u_dot_val++; blocked_dofs_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GeneralizedTrapezoidal::corrector(const SolutionType & type, Real delta_t, Array<Real> & u, Array<Real> & u_dot, const Array<bool> & blocked_dofs, const Array<Real> & delta) const { AKANTU_DEBUG_IN(); switch (type) { case _temperature: this->allCorrector<_temperature>(delta_t, u, u_dot, blocked_dofs, delta); break; case _temperature_rate: this->allCorrector<_temperature_rate>(delta_t, u, u_dot, blocked_dofs, delta); break; default: AKANTU_EXCEPTION("The corrector type : " << type << " is not supported by this type of integration scheme"); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real GeneralizedTrapezoidal::getTemperatureCoefficient( const SolutionType & type, Real delta_t) const { switch (type) { case _temperature: return 1.; case _temperature_rate: return alpha * delta_t; default: AKANTU_EXCEPTION("The corrector type : " << type << " is not supported by this type of integration scheme"); } } /* -------------------------------------------------------------------------- */ Real GeneralizedTrapezoidal::getTemperatureRateCoefficient( const SolutionType & type, Real delta_t) const { switch (type) { case _temperature: return 1. / (alpha * delta_t); case _temperature_rate: return 1.; default: AKANTU_EXCEPTION("The corrector type : " << type << " is not supported by this type of integration scheme"); } } /* -------------------------------------------------------------------------- */ template <IntegrationScheme::SolutionType type> void GeneralizedTrapezoidal::allCorrector(Real delta_t, Array<Real> & u, Array<Real> & u_dot, const Array<bool> & blocked_dofs, const Array<Real> & delta) const { AKANTU_DEBUG_IN(); UInt nb_nodes = u.getSize(); UInt nb_degree_of_freedom = u.getNbComponent() * nb_nodes; Real e = getTemperatureCoefficient(type, delta_t); Real d = getTemperatureRateCoefficient(type, delta_t); Real * u_val = u.storage(); Real * u_dot_val = u_dot.storage(); Real * delta_val = delta.storage(); bool * blocked_dofs_val = blocked_dofs.storage(); for (UInt dof = 0; dof < nb_degree_of_freedom; dof++) { if (!(*blocked_dofs_val)) { *u_val += e ** delta_val; *u_dot_val += d ** delta_val; } u_val++; u_dot_val++; delta_val++; blocked_dofs_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GeneralizedTrapezoidal::assembleJacobian(const SolutionType & type, Real delta_t) { AKANTU_DEBUG_IN(); SparseMatrix & J = this->dof_manager.getMatrix("J"); const SparseMatrix & M = this->dof_manager.getMatrix("M"); const SparseMatrix & K = this->dof_manager.getMatrix("K"); bool does_j_need_update = false; does_j_need_update |= M.getRelease() != m_release; does_j_need_update |= K.getRelease() != k_release; if (!does_j_need_update) { AKANTU_DEBUG_OUT(); return; } J.clear(); Real c = this->getTemperatureRateCoefficient(type, delta_t); Real e = this->getTemperatureCoefficient(type, delta_t); J.add(M, e); J.add(K, c); m_release = M.getRelease(); k_release = K.getRelease(); AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu diff --git a/src/model/integration_scheme/generalized_trapezoidal.hh b/src/model/integration_scheme/generalized_trapezoidal.hh index 7a2256941..d2e2d4f83 100644 --- a/src/model/integration_scheme/generalized_trapezoidal.hh +++ b/src/model/integration_scheme/generalized_trapezoidal.hh @@ -1,166 +1,166 @@ /** * @file generalized_trapezoidal.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Jul 04 2011 * @date last modification: Fri Oct 23 2015 * * @brief Generalized Trapezoidal Method. This implementation is taken from * Méthodes numériques en mécanique des solides by Alain Curnier \note{ISBN: * 2-88074-247-1} * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_GENERALIZED_TRAPEZOIDAL_HH__ #define __AKANTU_GENERALIZED_TRAPEZOIDAL_HH__ #include "integration_scheme_1st_order.hh" -__BEGIN_AKANTU__ +namespace akantu { /** * The two differentiate equation (thermal and kinematic) are : * @f{eqnarray*}{ * C\dot{u}_{n+1} + Ku_{n+1} = q_{n+1}\\ * u_{n+1} = u_{n} + (1-\alpha) \Delta t \dot{u}_{n} + \alpha \Delta t *\dot{u}_{n+1} * @f} * * To solve it : * Predictor : * @f{eqnarray*}{ * u^0_{n+1} &=& u_{n} + (1-\alpha) \Delta t v_{n} \\ * \dot{u}^0_{n+1} &=& \dot{u}_{n} * @f} * * Solve : * @f[ (a C + b K^i_{n+1}) w = q_{n+1} - f^i_{n+1} - C \dot{u}^i_{n+1} @f] * * Corrector : * @f{eqnarray*}{ * \dot{u}^{i+1}_{n+1} &=& \dot{u}^{i}_{n+1} + a w \\ * u^{i+1}_{n+1} &=& u^{i}_{n+1} + b w * @f} * * a and b depends on the resolution method : temperature (u) or temperature *rate (@f$\dot{u}@f$) * * For temperature : @f$ w = \delta u, a = 1 / (\alpha \Delta t) , b = 1 @f$ @n * For temperature rate : @f$ w = \delta \dot{u}, a = 1, b = \alpha \Delta t @f$ */ class GeneralizedTrapezoidal : public IntegrationScheme1stOrder { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: GeneralizedTrapezoidal(DOFManager & dof_manager, const ID & dof_id, Real alpha = 0); virtual ~GeneralizedTrapezoidal(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void predictor(Real delta_t, Array<Real> & u, Array<Real> & u_dot, const Array<bool> & blocked_dofs) const; virtual void corrector(const SolutionType & type, Real delta_t, Array<Real> & u, Array<Real> & u_dot, const Array<bool> & blocked_dofs, const Array<Real> & delta) const; virtual void assembleJacobian(const SolutionType & type, Real time_step); public: /// the coeffichent @f{b@f} in the description Real getTemperatureCoefficient(const SolutionType & type, Real delta_t) const; /// the coeffichent @f{a@f} in the description Real getTemperatureRateCoefficient(const SolutionType & type, Real delta_t) const; private: template <SolutionType type> void allCorrector(Real delta_t, Array<Real> & u, Array<Real> & u_dot, const Array<bool> & blocked_dofs, const Array<Real> & delta) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(Alpha, alpha, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// the @f$\alpha@f$ parameter Real alpha; /// last release of M matrix UInt m_release; /// last release of K matrix UInt k_release; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /** * Forward Euler (explicit) -> condition on delta_t */ class ForwardEuler : public GeneralizedTrapezoidal { public: ForwardEuler(DOFManager & dof_manager, const ID & dof_id) : GeneralizedTrapezoidal(dof_manager, dof_id, 0.){}; }; /** * Trapezoidal rule (implicit), midpoint rule or Crank-Nicolson */ class TrapezoidalRule1 : public GeneralizedTrapezoidal { public: TrapezoidalRule1(DOFManager & dof_manager, const ID & dof_id) : GeneralizedTrapezoidal(dof_manager, dof_id, .5){}; }; /** * Backward Euler (implicit) */ class BackwardEuler : public GeneralizedTrapezoidal { public: BackwardEuler(DOFManager & dof_manager, const ID & dof_id) : GeneralizedTrapezoidal(dof_manager, dof_id, 1.){}; }; /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_GENERALIZED_TRAPEZOIDAL_HH__ */ diff --git a/src/model/integration_scheme/integration_scheme.cc b/src/model/integration_scheme/integration_scheme.cc index 1e92fdaed..82c60d006 100644 --- a/src/model/integration_scheme/integration_scheme.cc +++ b/src/model/integration_scheme/integration_scheme.cc @@ -1,92 +1,92 @@ /** * @file integration_scheme.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Fri Oct 23 15:33:36 2015 * * @brief Common interface to all interface schemes * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "integration_scheme.hh" #include "dof_manager.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ IntegrationScheme::IntegrationScheme(DOFManager & dof_manager, const ID & dof_id, UInt order) : Parsable(_st_integration_scheme, dof_id), dof_manager(dof_manager), dof_id(dof_id), order(order) {} /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ // /// standard output stream operator for SolutionType // std::ostream & operator<<(std::ostream & stream, // const IntegrationScheme::SolutionType & type) { // switch (type) { // case IntegrationScheme::_displacement: // stream << "displacement"; // break; // case IntegrationScheme::_temperature: // stream << "temperature"; // break; // case IntegrationScheme::_velocity: // stream << "velocity"; // break; // case IntegrationScheme::_temperature_rate: // stream << "temperature_rate"; // break; // case IntegrationScheme::_acceleration: // stream << "acceleration"; // break; // } // return stream; // } /* -------------------------------------------------------------------------- */ /// standard input stream operator for SolutionType std::istream & operator>>(std::istream & stream, IntegrationScheme::SolutionType & type) { std::string str; stream >> str; if (str == "displacement") type = IntegrationScheme::_displacement; else if (str == "temperature") type = IntegrationScheme::_temperature; else if (str == "velocity") type = IntegrationScheme::_velocity; else if (str == "temperature_rate") type = IntegrationScheme::_temperature_rate; else if (str == "acceleration") type = IntegrationScheme::_acceleration; else { stream.setstate(std::ios::failbit); } return stream; } -__END_AKANTU__ +} // akantu diff --git a/src/model/integration_scheme/integration_scheme.hh b/src/model/integration_scheme/integration_scheme.hh index 3a8d9c454..6a11db54f 100644 --- a/src/model/integration_scheme/integration_scheme.hh +++ b/src/model/integration_scheme/integration_scheme.hh @@ -1,107 +1,107 @@ /** * @file integration_scheme.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Mon Sep 28 10:43:18 2015 * * @brief This class is just a base class for the integration schemes * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "parsable.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_INTEGRATION_SCHEME_HH__ #define __AKANTU_INTEGRATION_SCHEME_HH__ namespace akantu { class DOFManager; } -__BEGIN_AKANTU__ +namespace akantu { class IntegrationScheme : public Parsable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: enum SolutionType { _not_defined = -1, _displacement = 0, _temperature = 0, _velocity = 1, _temperature_rate = 1, _acceleration = 2, }; IntegrationScheme(DOFManager & dof_manager, const ID & dof_id, UInt order); virtual ~IntegrationScheme() {} /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// generic interface of a predictor virtual void predictor(Real delta_t) = 0; /// generic interface of a corrector virtual void corrector(const SolutionType & type, Real delta_t) = 0; /// assemble the jacobian matrix virtual void assembleJacobian(const SolutionType & type, Real delta_t) = 0; /// assemble the residual virtual void assembleResidual(bool is_lumped) = 0; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// return the order of the integration scheme UInt getOrder() const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// The underlying dofmanager DOFManager & dof_manager; /// The id of the dof treated by this integration scheme. ID dof_id; /// The order of the integrator UInt order; }; /* -------------------------------------------------------------------------- */ // std::ostream & operator<<(std::ostream & stream, // const IntegrationScheme::SolutionType & type); std::istream & operator>>(std::istream & stream, IntegrationScheme::SolutionType & type); /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_INTEGRATION_SCHEME_HH__ */ diff --git a/src/model/integration_scheme/integration_scheme_1st_order.cc b/src/model/integration_scheme/integration_scheme_1st_order.cc index 99c607d45..bfdce85eb 100644 --- a/src/model/integration_scheme/integration_scheme_1st_order.cc +++ b/src/model/integration_scheme/integration_scheme_1st_order.cc @@ -1,88 +1,88 @@ /** * @file integration_scheme_1st_order.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Fri Oct 23 12:31:32 2015 * * @brief Implementation of the common functions for 1st order time *integrations * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "integration_scheme_1st_order.hh" #include "dof_manager.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ void IntegrationScheme1stOrder::predictor(Real delta_t) { AKANTU_DEBUG_IN(); Array<Real> & u = this->dof_manager.getDOFs(this->dof_id); Array<Real> & u_dot = this->dof_manager.getDOFsDerivatives(this->dof_id, 1); const Array<bool> & blocked_dofs = this->dof_manager.getBlockedDOFs(this->dof_id); this->predictor(delta_t, u, u_dot, blocked_dofs); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void IntegrationScheme1stOrder::corrector(const SolutionType & type, Real delta_t) { AKANTU_DEBUG_IN(); Array<Real> & u = this->dof_manager.getDOFs(this->dof_id); Array<Real> & u_dot = this->dof_manager.getDOFsDerivatives(this->dof_id, 1); const Array<Real> & solution = this->dof_manager.getSolution(this->dof_id); const Array<bool> & blocked_dofs = this->dof_manager.getBlockedDOFs(this->dof_id); this->corrector(type, delta_t, u, u_dot, blocked_dofs, solution); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void IntegrationScheme1stOrder::assembleResidual(bool is_lumped) { AKANTU_DEBUG_IN(); const Array<Real> & first_derivative = dof_manager.getDOFsDerivatives(this->dof_id, 1); if (!is_lumped) { this->dof_manager.assembleMatMulVectToResidual(this->dof_id, "C", first_derivative, -1); } else { this->dof_manager.assembleLumpedMatMulVectToResidual(this->dof_id, "C", first_derivative, -1); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/integration_scheme/integration_scheme_1st_order.hh b/src/model/integration_scheme/integration_scheme_1st_order.hh index af70e2a4e..7f73dc8b9 100644 --- a/src/model/integration_scheme/integration_scheme_1st_order.hh +++ b/src/model/integration_scheme/integration_scheme_1st_order.hh @@ -1,93 +1,93 @@ /** * @file integration_scheme_1st_order.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Oct 23 2015 * * @brief Interface of the time integrator of first order * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "integration_scheme.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_INTEGRATION_SCHEME_1ST_ORDER_HH__ #define __AKANTU_INTEGRATION_SCHEME_1ST_ORDER_HH__ -__BEGIN_AKANTU__ +namespace akantu { class IntegrationScheme1stOrder : public IntegrationScheme { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: IntegrationScheme1stOrder(DOFManager & dof_manager, const ID & dof_id) : IntegrationScheme(dof_manager, dof_id, 1){}; virtual ~IntegrationScheme1stOrder(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// generic interface of a predictor virtual void predictor(Real delta_t); /// generic interface of a corrector virtual void corrector(const SolutionType & type, Real delta_t); /// assemble the residual virtual void assembleResidual(bool is_lumped); protected: /// generic interface of a predictor of 1st order virtual void predictor(Real delta_t, Array<Real> & u, Array<Real> & u_dot, const Array<bool> & boundary) const = 0; /// generic interface of a corrector of 1st order virtual void corrector(const SolutionType & type, Real delta_t, Array<Real> & u, Array<Real> & u_dot, const Array<bool> & boundary, const Array<Real> & delta) const = 0; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ protected: virtual Real getTemperatureCoefficient(const SolutionType & type, Real delta_t) const = 0; virtual Real getTemperatureRateCoefficient(const SolutionType & type, Real delta_t) const = 0; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; -__END_AKANTU__ +} // akantu #include "generalized_trapezoidal.hh" #endif /* __AKANTU_INTEGRATION_SCHEME_1ST_ORDER_HH__ */ diff --git a/src/model/integration_scheme/integration_scheme_2nd_order.cc b/src/model/integration_scheme/integration_scheme_2nd_order.cc index 190e5b3b5..6af699f99 100644 --- a/src/model/integration_scheme/integration_scheme_2nd_order.cc +++ b/src/model/integration_scheme/integration_scheme_2nd_order.cc @@ -1,100 +1,100 @@ /** * @file integration_scheme_2nd_order.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Tue Oct 20 10:41:12 2015 * * @brief Implementation of the common part of 2nd order integration schemes * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "integration_scheme_2nd_order.hh" #include "dof_manager.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ void IntegrationScheme2ndOrder::predictor(Real delta_t) { AKANTU_DEBUG_IN(); Array<Real> & u = this->dof_manager.getDOFs(this->dof_id); Array<Real> & u_dot = this->dof_manager.getDOFsDerivatives(this->dof_id, 1); Array<Real> & u_dot_dot = this->dof_manager.getDOFsDerivatives(this->dof_id, 2); const Array<bool> & blocked_dofs = this->dof_manager.getBlockedDOFs(this->dof_id); this->predictor(delta_t, u, u_dot, u_dot_dot, blocked_dofs); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void IntegrationScheme2ndOrder::corrector(const SolutionType & type, Real delta_t) { AKANTU_DEBUG_IN(); Array<Real> & u = this->dof_manager.getDOFs(this->dof_id); Array<Real> & u_dot = this->dof_manager.getDOFsDerivatives(this->dof_id, 1); Array<Real> & u_dot_dot = this->dof_manager.getDOFsDerivatives(this->dof_id, 2); const Array<Real> & solution = this->dof_manager.getSolution(this->dof_id); const Array<bool> & blocked_dofs = this->dof_manager.getBlockedDOFs(this->dof_id); this->corrector(type, delta_t, u, u_dot, u_dot_dot, blocked_dofs, solution); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void IntegrationScheme2ndOrder::assembleResidual(bool is_lumped) { AKANTU_DEBUG_IN(); if (this->dof_manager.hasMatrix("C")) { const Array<Real> & first_derivative = this->dof_manager.getDOFsDerivatives(this->dof_id, 1); this->dof_manager.assembleMatMulVectToResidual(this->dof_id, "C", first_derivative, -1); } const Array<Real> & second_derivative = this->dof_manager.getDOFsDerivatives(this->dof_id, 2); if (!is_lumped) { this->dof_manager.assembleMatMulVectToResidual(this->dof_id, "M", second_derivative, -1); } else { this->dof_manager.assembleLumpedMatMulVectToResidual(this->dof_id, "M", second_derivative, -1); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/integration_scheme/integration_scheme_2nd_order.hh b/src/model/integration_scheme/integration_scheme_2nd_order.hh index ba2e9b62b..9ae6b095e 100644 --- a/src/model/integration_scheme/integration_scheme_2nd_order.hh +++ b/src/model/integration_scheme/integration_scheme_2nd_order.hh @@ -1,104 +1,104 @@ /** * @file integration_scheme_2nd_order.hh * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Oct 23 2015 * * @brief Interface of the integrator of second order * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" #include "integration_scheme.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_INTEGRATION_SCHEME_2ND_ORDER_HH__ #define __AKANTU_INTEGRATION_SCHEME_2ND_ORDER_HH__ namespace akantu { class SparseMatrix; } -__BEGIN_AKANTU__ +namespace akantu { class IntegrationScheme2ndOrder : public IntegrationScheme { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: IntegrationScheme2ndOrder(DOFManager & dof_manager, const ID & dof_id) : IntegrationScheme(dof_manager, dof_id, 2){}; virtual ~IntegrationScheme2ndOrder(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// generic interface of a predictor virtual void predictor(Real delta_t); /// generic interface of a corrector virtual void corrector(const SolutionType & type, Real delta_t); virtual void assembleResidual(bool is_lumped); protected: /// generic interface of a predictor of 2nd order virtual void predictor(Real delta_t, Array<Real> & u, Array<Real> & u_dot, Array<Real> & u_dot_dot, const Array<bool> & blocked_dofs) const = 0; /// generic interface of a corrector of 2nd order virtual void corrector(const SolutionType & type, Real delta_t, Array<Real> & u, Array<Real> & u_dot, Array<Real> & u_dot_dot, const Array<bool> & blocked_dofs, const Array<Real> & delta) const = 0; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ protected: virtual Real getAccelerationCoefficient(const SolutionType & type, Real delta_t) const = 0; virtual Real getVelocityCoefficient(const SolutionType & type, Real delta_t) const = 0; virtual Real getDisplacementCoefficient(const SolutionType & type, Real delta_t) const = 0; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; -__END_AKANTU__ +} // akantu #include "newmark-beta.hh" #endif /* __AKANTU_INTEGRATION_SCHEME_2ND_ORDER_HH__ */ diff --git a/src/model/integration_scheme/newmark-beta.cc b/src/model/integration_scheme/newmark-beta.cc index 9527dfc6c..44ba3091a 100644 --- a/src/model/integration_scheme/newmark-beta.cc +++ b/src/model/integration_scheme/newmark-beta.cc @@ -1,260 +1,260 @@ /** * @file newmark-beta.cc * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Oct 05 2010 * @date last modification: Thu Jun 05 2014 * * @brief implementation of the newmark-@f$\beta@f$ integration scheme. This * implementation is taken from Méthodes numériques en mécanique des solides by * Alain Curnier \note{ISBN: 2-88074-247-1} * * @section LICENSE * * Copyright (©) 2010-2012, 2014 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "newmark-beta.hh" #include "dof_manager.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ NewmarkBeta::NewmarkBeta(DOFManager & dof_manager, const ID & dof_id, Real alpha, Real beta) : IntegrationScheme2ndOrder(dof_manager, dof_id), beta(beta), alpha(alpha), k(0.), h(0.), m_release(0), k_release(0), c_release(0) { this->registerParam("alpha", this->alpha, alpha, _pat_parsmod, "The alpha parameter"); this->registerParam("beta", this->beta, beta, _pat_parsmod, "The beta parameter"); } /* -------------------------------------------------------------------------- */ /* * @f$ \tilde{u_{n+1}} = u_{n} + \Delta t \dot{u}_n + \frac{\Delta t^2}{2} * \ddot{u}_n @f$ * @f$ \tilde{\dot{u}_{n+1}} = \dot{u}_{n} + \Delta t \ddot{u}_{n} @f$ * @f$ \tilde{\ddot{u}_{n}} = \ddot{u}_{n} @f$ */ void NewmarkBeta::predictor(Real delta_t, Array<Real> & u, Array<Real> & u_dot, Array<Real> & u_dot_dot, const Array<bool> & blocked_dofs) const { AKANTU_DEBUG_IN(); UInt nb_nodes = u.getSize(); UInt nb_degree_of_freedom = u.getNbComponent() * nb_nodes; Real * u_val = u.storage(); Real * u_dot_val = u_dot.storage(); Real * u_dot_dot_val = u_dot_dot.storage(); bool * blocked_dofs_val = blocked_dofs.storage(); for (UInt d = 0; d < nb_degree_of_freedom; d++) { if (!(*blocked_dofs_val)) { Real dt_a_n = delta_t * *u_dot_dot_val; *u_val += (1 - k * alpha) * delta_t * *u_dot_val + (.5 - h * alpha * beta) * delta_t * dt_a_n; *u_dot_val = (1 - k) * *u_dot_val + (1 - h * beta) * dt_a_n; *u_dot_dot_val = (1 - h) * *u_dot_dot_val; } u_val++; u_dot_val++; u_dot_dot_val++; blocked_dofs_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void NewmarkBeta::corrector(const SolutionType & type, Real delta_t, Array<Real> & u, Array<Real> & u_dot, Array<Real> & u_dot_dot, const Array<bool> & blocked_dofs, const Array<Real> & delta) const { AKANTU_DEBUG_IN(); switch (type) { case _acceleration: { this->allCorrector<_acceleration>(delta_t, u, u_dot, u_dot_dot, blocked_dofs, delta); break; } case _velocity: { this->allCorrector<_velocity>(delta_t, u, u_dot, u_dot_dot, blocked_dofs, delta); break; } case _displacement: { this->allCorrector<_displacement>(delta_t, u, u_dot, u_dot_dot, blocked_dofs, delta); break; } default: AKANTU_EXCEPTION("The corrector type : " << type << " is not supported by this type of integration scheme"); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real NewmarkBeta::getAccelerationCoefficient(const SolutionType & type, Real delta_t) const { switch (type) { case _acceleration: return 1.; case _velocity: return 1. / (beta * delta_t); case _displacement: return 1. / (alpha * beta * delta_t * delta_t); default: AKANTU_EXCEPTION("The corrector type : " << type << " is not supported by this type of integration scheme"); } } /* -------------------------------------------------------------------------- */ Real NewmarkBeta::getVelocityCoefficient(const SolutionType & type, Real delta_t) const { switch (type) { case _acceleration: return beta * delta_t; case _velocity: return 1.; case _displacement: return 1. / (alpha * delta_t); default: AKANTU_EXCEPTION("The corrector type : " << type << " is not supported by this type of integration scheme"); } } /* -------------------------------------------------------------------------- */ Real NewmarkBeta::getDisplacementCoefficient(const SolutionType & type, Real delta_t) const { switch (type) { case _acceleration: return alpha * beta * delta_t * delta_t; case _velocity: return alpha * delta_t; case _displacement: return 1.; default: AKANTU_EXCEPTION("The corrector type : " << type << " is not supported by this type of integration scheme"); } } /* -------------------------------------------------------------------------- */ template <IntegrationScheme::SolutionType type> void NewmarkBeta::allCorrector(Real delta_t, Array<Real> & u, Array<Real> & u_dot, Array<Real> & u_dot_dot, const Array<bool> & blocked_dofs, const Array<Real> & delta) const { AKANTU_DEBUG_IN(); UInt nb_nodes = u.getSize(); UInt nb_degree_of_freedom = u.getNbComponent() * nb_nodes; Real c = getAccelerationCoefficient(type, delta_t); Real d = getVelocityCoefficient(type, delta_t); Real e = getDisplacementCoefficient(type, delta_t); Real * u_val = u.storage(); Real * u_dot_val = u_dot.storage(); Real * u_dot_dot_val = u_dot_dot.storage(); Real * delta_val = delta.storage(); bool * blocked_dofs_val = blocked_dofs.storage(); for (UInt dof = 0; dof < nb_degree_of_freedom; dof++) { if (!(*blocked_dofs_val)) { *u_val += e * *delta_val; *u_dot_val += d * *delta_val; *u_dot_dot_val += c * *delta_val; } u_val++; u_dot_val++; u_dot_dot_val++; delta_val++; blocked_dofs_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void NewmarkBeta::assembleJacobian(const SolutionType & type, Real delta_t) { AKANTU_DEBUG_IN(); SparseMatrix & J = this->dof_manager.getMatrix("J"); const SparseMatrix & M = this->dof_manager.getMatrix("M"); const SparseMatrix & K = this->dof_manager.getMatrix("K"); bool does_j_need_update = false; does_j_need_update |= M.getRelease() != m_release; does_j_need_update |= K.getRelease() != k_release; if (this->dof_manager.hasMatrix("C")) { const SparseMatrix & C = this->dof_manager.getMatrix("C"); does_j_need_update |= C.getRelease() != c_release; } if (!does_j_need_update) { AKANTU_DEBUG_OUT(); return; } J.clear(); Real c = this->getAccelerationCoefficient(type, delta_t); Real e = this->getDisplacementCoefficient(type, delta_t); if (!(e == 0.)) { // in explicit this coefficient is exactly 0. J.add(K, e); } J.add(M, c); m_release = M.getRelease(); k_release = K.getRelease(); if (this->dof_manager.hasMatrix("C")) { Real d = this->getVelocityCoefficient(type, delta_t); const SparseMatrix & C = this->dof_manager.getMatrix("C"); J.add(C, d); c_release = C.getRelease(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/integration_scheme/newmark-beta.hh b/src/model/integration_scheme/newmark-beta.hh index 6272757e4..ac976a2ed 100644 --- a/src/model/integration_scheme/newmark-beta.hh +++ b/src/model/integration_scheme/newmark-beta.hh @@ -1,195 +1,195 @@ /** * @file newmark-beta.hh * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Oct 05 2010 * @date last modification: Fri Oct 23 2015 * * @brief implementation of the newmark-@f$\beta@f$ integration scheme. This * implementation is taken from Méthodes numériques en mécanique des solides by * Alain Curnier \note{ISBN: 2-88074-247-1} * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NEWMARK_BETA_HH__ #define __AKANTU_NEWMARK_BETA_HH__ /* -------------------------------------------------------------------------- */ #include "integration_scheme_2nd_order.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /** * The three differentiate equations (dynamic and cinematic) are : * @f{eqnarray*}{ * M \ddot{u}_{n+1} + C \dot{u}_{n+1} + K u_{n+1} &=& q_{n+1} \\ * u_{n+1} &=& u_{n} + (1 - \alpha) \Delta t \dot{u}_{n} + \alpha \Delta t *\dot{u}_{n+1} + (1/2 - \alpha) \Delta t^2 \ddot{u}_n \\ * \dot{u}_{n+1} &=& \dot{u}_{n} + (1 - \beta) \Delta t \ddot{u}_{n} + \beta *\Delta t \ddot{u}_{n+1} * @f} * * Predictor: * @f{eqnarray*}{ * u^{0}_{n+1} &=& u_{n} + \Delta t \dot{u}_n + \frac{\Delta t^2}{2} *\ddot{u}_n \\ * \dot{u}^{0}_{n+1} &=& \dot{u}_{n} + \Delta t \ddot{u}_{n} \\ * \ddot{u}^{0}_{n+1} &=& \ddot{u}_{n} * @f} * * Solve : * @f[ (c M + d C + e K^i_{n+1}) w = = q_{n+1} - f^i_{n+1} - C \dot{u}^i_{n+1} *- M \ddot{u}^i_{n+1} @f] * * Corrector : * @f{eqnarray*}{ * \ddot{u}^{i+1}_{n+1} &=& \ddot{u}^{i}_{n+1} + c w \\ * \dot{u}^{i+1}_{n+1} &=& \dot{u}^{i}_{n+1} + d w \\ * u^{i+1}_{n+1} &=& u^{i}_{n+1} + e w * @f} * * c, d and e are parameters depending on the method used to solve the equations *@n * For acceleration : @f$ w = \delta \ddot{u}, e = \alpha \beta \Delta t^2, d = *\beta \Delta t, c = 1 @f$ @n * For velocity : @f$ w = \delta \dot{u}, e = 1/\beta \Delta t, d = *1, c = \alpha \Delta t @f$ @n * For displacement : @f$ w = \delta u, e = 1, d = *1/\alpha \Delta t, c = 1/\alpha \beta \Delta t^2 @f$ */ class NewmarkBeta : public IntegrationScheme2ndOrder { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NewmarkBeta(DOFManager & dof_manager, const ID & dof_id, Real alpha = 0., Real beta = 0.); ~NewmarkBeta(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void predictor(Real delta_t, Array<Real> & u, Array<Real> & u_dot, Array<Real> & u_dot_dot, const Array<bool> & blocked_dofs) const; void corrector(const SolutionType & type, Real delta_t, Array<Real> & u, Array<Real> & u_dot, Array<Real> & u_dot_dot, const Array<bool> & blocked_dofs, const Array<Real> & delta) const; void assembleJacobian(const SolutionType & type, Real delta_t); public: Real getAccelerationCoefficient(const SolutionType & type, Real delta_t) const; Real getVelocityCoefficient(const SolutionType & type, Real delta_t) const; Real getDisplacementCoefficient(const SolutionType & type, Real delta_t) const; private: template <SolutionType type> void allCorrector(Real delta_t, Array<Real> & u, Array<Real> & u_dot, Array<Real> & u_dot_dot, const Array<bool> & blocked_dofs, const Array<Real> & delta) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(Beta, beta, Real); AKANTU_GET_MACRO(Alpha, alpha, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// the @f$\beta@f$ parameter Real beta; /// the @f$\alpha@f$ parameter Real alpha; Real k; Real h; /// last release of M matrix UInt m_release; /// last release of K matrix UInt k_release; /// last release of C matrix UInt c_release; }; /** * central difference method (explicit) * undamped stability condition : * @f$ \Delta t = \alpha \Delta t_{crit} = \frac{2}{\omega_{max}} \leq \min_{e} *\frac{l_e}{c_e} * */ class CentralDifference : public NewmarkBeta { public: CentralDifference(DOFManager & dof_manager, const ID & dof_id) : NewmarkBeta(dof_manager, dof_id, 0., 1. / 2.){}; }; //#include "integration_scheme/central_difference.hh" /// undamped trapezoidal rule (implicit) class TrapezoidalRule2 : public NewmarkBeta { public: TrapezoidalRule2(DOFManager & dof_manager, const ID & dof_id) : NewmarkBeta(dof_manager, dof_id, 1. / 2., 1. / 2.){}; }; /// Fox-Goodwin rule (implicit) class FoxGoodwin : public NewmarkBeta { public: FoxGoodwin(DOFManager & dof_manager, const ID & dof_id) : NewmarkBeta(dof_manager, dof_id, 1. / 6., 1. / 2.){}; }; /// Linear acceleration (implicit) class LinearAceleration : public NewmarkBeta { public: LinearAceleration(DOFManager & dof_manager, const ID & dof_id) : NewmarkBeta(dof_manager, dof_id, 1. / 3., 1. / 2.){}; }; /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_NEWMARK_BETA_HH__ */ diff --git a/src/model/integration_scheme/pseudo_time.cc b/src/model/integration_scheme/pseudo_time.cc index 2acfd2ad2..c19ff6ffe 100644 --- a/src/model/integration_scheme/pseudo_time.cc +++ b/src/model/integration_scheme/pseudo_time.cc @@ -1,85 +1,85 @@ /** * @file pseudo_time.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Wed Feb 17 09:49:10 2016 * * @brief Implementation of a really simple integration 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "pseudo_time.hh" #include "dof_manager.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ PseudoTime::PseudoTime(DOFManager & dof_manager, const ID & dof_id) : IntegrationScheme(dof_manager, dof_id, 0), k_release(0) {} /* -------------------------------------------------------------------------- */ void PseudoTime::predictor(Real) {} /* -------------------------------------------------------------------------- */ void PseudoTime::corrector(const SolutionType &, Real) { Array<Real> & us = this->dof_manager.getDOFs(this->dof_id); const Array<Real> & deltas = this->dof_manager.getSolution(this->dof_id); const Array<bool> & blocked_dofs = this->dof_manager.getBlockedDOFs(this->dof_id); UInt nb_degree_of_freedom = deltas.getSize(); auto u_it = us.begin_reinterpret(nb_degree_of_freedom); auto bld_it = blocked_dofs.begin_reinterpret(nb_degree_of_freedom); for (const auto & delta : deltas) { const auto & bld = *bld_it; auto & u = *u_it; if (! bld) u += delta; ++u_it; ++bld_it; } } /* -------------------------------------------------------------------------- */ void PseudoTime::assembleJacobian(const SolutionType &, Real) { SparseMatrix & J = this->dof_manager.getMatrix("J"); const SparseMatrix & K = this->dof_manager.getMatrix("K"); if (K.getRelease() == k_release) return; J.clear(); J.add(K); k_release = K.getRelease(); } /* -------------------------------------------------------------------------- */ void PseudoTime::assembleResidual(bool) {} /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/integration_scheme/pseudo_time.hh b/src/model/integration_scheme/pseudo_time.hh index 9be2d22d3..cfd37f8aa 100644 --- a/src/model/integration_scheme/pseudo_time.hh +++ b/src/model/integration_scheme/pseudo_time.hh @@ -1,70 +1,70 @@ /** * @file pseudo_time.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Wed Feb 17 09:46:05 2016 * * @brief Pseudo time integration 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "integration_scheme.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_PSEUDO_TIME_HH__ #define __AKANTU_PSEUDO_TIME_HH__ -__BEGIN_AKANTU__ +namespace akantu { class PseudoTime : public IntegrationScheme { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: PseudoTime(DOFManager & dof_manager, const ID & dof_id); virtual ~PseudoTime() {} /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// generic interface of a predictor virtual void predictor(Real delta_t); /// generic interface of a corrector virtual void corrector(const SolutionType & type, Real delta_t); /// assemble the jacobian matrix virtual void assembleJacobian(const SolutionType & type, Real delta_t); /// assemble the residual virtual void assembleResidual(bool is_lumped); protected: /// last release of K matrix UInt k_release; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_PSEUDO_TIME_HH__ */ diff --git a/src/model/model.cc b/src/model/model.cc index a439f3dfb..abf830ba8 100644 --- a/src/model/model.cc +++ b/src/model/model.cc @@ -1,342 +1,342 @@ /** * @file model.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Oct 03 2011 * @date last modification: Thu Nov 19 2015 * * @brief implementation of model common parts * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "model.hh" #include "element_group.hh" #include "synchronizer_registry.hh" #include "data_accessor.hh" #include "static_communicator.hh" #include "element_synchronizer.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ Model::Model(Mesh& mesh, UInt dim, const ID & id, const MemoryID & memory_id) : Memory(id, memory_id), ModelSolver(mesh, id, memory_id), mesh(mesh), spatial_dimension(dim == _all_dimensions ? mesh.getSpatialDimension() : dim), is_pbc_slave_node(0,1,"is_pbc_slave_node") , parser(&getStaticParser()) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Model::~Model() { AKANTU_DEBUG_IN(); FEEngineMap::iterator it; for (it = fems.begin(); it != fems.end(); ++it) { if (it->second) delete it->second; } for (it = fems_boundary.begin(); it != fems_boundary.end(); ++it) { if (it->second) delete it->second; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Model::setParser(Parser & parser) { this->parser = &parser; } /* -------------------------------------------------------------------------- */ void Model::initFull(__attribute__((unused)) const ModelOptions & options) { AKANTU_DEBUG_IN(); initModel(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Model::initPBC() { std::map<UInt, UInt>::iterator it = pbc_pair.begin(); std::map<UInt, UInt>::iterator end = pbc_pair.end(); is_pbc_slave_node.resize(mesh.getNbNodes()); #ifndef AKANTU_NDEBUG Array<Real>::const_vector_iterator coord_it = mesh.getNodes().begin(this->spatial_dimension); #endif while (it != end) { UInt i1 = (*it).first; is_pbc_slave_node(i1) = true; #ifndef AKANTU_NDEBUG UInt i2 = (*it).second; UInt slave = mesh.isDistributed() ? mesh.getGlobalNodesIds()(i1) : i1; UInt master = mesh.isDistributed() ? mesh.getGlobalNodesIds()(i2) : i2; AKANTU_DEBUG_INFO("pairing " << slave << " (" << Vector<Real>(coord_it[i1]) << ") with " << master << " (" << Vector<Real>(coord_it[i2]) << ")"); #endif ++it; } } /* -------------------------------------------------------------------------- */ void Model::dumpGroup(const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); group.dump(); } /* -------------------------------------------------------------------------- */ void Model::dumpGroup(const std::string & group_name, const std::string & dumper_name) { ElementGroup & group = mesh.getElementGroup(group_name); group.dump(dumper_name); } /* -------------------------------------------------------------------------- */ void Model::dumpGroup() { GroupManager::element_group_iterator bit = mesh.element_group_begin(); GroupManager::element_group_iterator bend = mesh.element_group_end(); for (; bit != bend; ++bit) { bit->second->dump(); } } /* -------------------------------------------------------------------------- */ void Model::setGroupDirectory(const std::string & directory) { GroupManager::element_group_iterator bit = mesh.element_group_begin(); GroupManager::element_group_iterator bend = mesh.element_group_end(); for (; bit != bend; ++bit) { bit->second->setDirectory(directory); } } /* -------------------------------------------------------------------------- */ void Model::setGroupDirectory(const std::string & directory, const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); group.setDirectory(directory); } /* -------------------------------------------------------------------------- */ void Model::setGroupBaseName(const std::string & basename, const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); group.setBaseName(basename); } /* -------------------------------------------------------------------------- */ DumperIOHelper & Model::getGroupDumper(const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); return group.getDumper(); } /* -------------------------------------------------------------------------- */ // DUMPER stuff /* -------------------------------------------------------------------------- */ void Model::addDumpGroupFieldToDumper(const std::string & field_id, dumper::Field * field, DumperIOHelper & dumper) { #ifdef AKANTU_USE_IOHELPER dumper.registerField(field_id, field); #endif } /* -------------------------------------------------------------------------- */ void Model::addDumpField(const std::string & field_id) { this->addDumpFieldToDumper(mesh.getDefaultDumperName(), field_id); } /* -------------------------------------------------------------------------- */ void Model::addDumpFieldVector(const std::string & field_id) { this->addDumpFieldVectorToDumper(mesh.getDefaultDumperName(), field_id); } /* -------------------------------------------------------------------------- */ void Model::addDumpFieldTensor(const std::string & field_id) { this->addDumpFieldTensorToDumper(mesh.getDefaultDumperName(), field_id); } /* -------------------------------------------------------------------------- */ void Model::setBaseName(const std::string & field_id) { mesh.setBaseName(field_id); } /* -------------------------------------------------------------------------- */ void Model::setBaseNameToDumper(const std::string & dumper_name, const std::string & basename) { mesh.setBaseNameToDumper(dumper_name, basename); } /* -------------------------------------------------------------------------- */ void Model::addDumpFieldToDumper(const std::string & dumper_name, const std::string & field_id) { this->addDumpGroupFieldToDumper(dumper_name, field_id, "all", _ek_regular, false); } /* -------------------------------------------------------------------------- */ void Model::addDumpGroupField(const std::string & field_id, const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); this->addDumpGroupFieldToDumper(group.getDefaultDumperName(), field_id, group_name, _ek_regular, false); } /* -------------------------------------------------------------------------- */ void Model::removeDumpGroupField(const std::string & field_id, const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); this->removeDumpGroupFieldFromDumper(group.getDefaultDumperName(), field_id, group_name); } /* -------------------------------------------------------------------------- */ void Model::removeDumpGroupFieldFromDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); group.removeDumpFieldFromDumper(dumper_name, field_id); } /* -------------------------------------------------------------------------- */ void Model::addDumpFieldVectorToDumper(const std::string & dumper_name, const std::string & field_id) { this->addDumpGroupFieldToDumper(dumper_name, field_id, "all", _ek_regular, 3); } /* -------------------------------------------------------------------------- */ void Model::addDumpGroupFieldVector(const std::string & field_id, const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); this->addDumpGroupFieldVectorToDumper(group.getDefaultDumperName(), field_id, group_name); } /* -------------------------------------------------------------------------- */ void Model::addDumpGroupFieldVectorToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name) { this->addDumpGroupFieldToDumper(dumper_name, field_id, group_name, _ek_regular, true); } /* -------------------------------------------------------------------------- */ void Model::addDumpFieldTensorToDumper(const std::string & dumper_name, const std::string & field_id) { this->addDumpGroupFieldToDumper(dumper_name, field_id, "all", _ek_regular, true); } /* -------------------------------------------------------------------------- */ void Model::addDumpGroupFieldToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name, const ElementKind & element_kind, bool padding_flag) { this->addDumpGroupFieldToDumper(dumper_name, field_id, group_name, this->spatial_dimension, element_kind, padding_flag); } /* -------------------------------------------------------------------------- */ void Model::addDumpGroupFieldToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name, UInt spatial_dimension, const ElementKind & element_kind, bool padding_flag) { #ifdef AKANTU_USE_IOHELPER dumper::Field * field = NULL; if (!field) field = this->createNodalFieldReal(field_id, group_name, padding_flag); if (!field) field = this->createNodalFieldUInt(field_id, group_name, padding_flag); if (!field) field = this->createNodalFieldBool(field_id, group_name, padding_flag); if (!field) field = this->createElementalField(field_id, group_name, padding_flag, spatial_dimension, element_kind); if (!field) field = this->mesh.createFieldFromAttachedData<UInt>(field_id, group_name, element_kind); if (!field) field = this->mesh.createFieldFromAttachedData<Real>(field_id, group_name, element_kind); if (!field) AKANTU_DEBUG_WARNING("No field could be found based on name: " << field_id); if (field) { DumperIOHelper & dumper = mesh.getGroupDumper(dumper_name, group_name); this->addDumpGroupFieldToDumper(field_id, field, dumper); } #endif } /* -------------------------------------------------------------------------- */ void Model::dump() { mesh.dump(); } /* -------------------------------------------------------------------------- */ void Model::setDirectory(const std::string & directory) { mesh.setDirectory(directory); } /* -------------------------------------------------------------------------- */ void Model::setDirectoryToDumper(const std::string & dumper_name, const std::string & directory) { mesh.setDirectoryToDumper(dumper_name, directory); } /* -------------------------------------------------------------------------- */ void Model::setTextModeToDumper() { mesh.setTextModeToDumper(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/model_solver.cc b/src/model/model_solver.cc index 4199f603f..6fafb2844 100644 --- a/src/model/model_solver.cc +++ b/src/model/model_solver.cc @@ -1,673 +1,673 @@ /** * @file model_solver.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Wed Aug 12 13:31:56 2015 * * @brief Implementation of ModelSolver * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "model_solver.hh" #include "dof_manager.hh" #include "non_linear_solver.hh" #include "time_step_solver.hh" #include "mesh.hh" #if defined(AKANTU_USE_MPI) #include "mpi_type_wrapper.hh" #endif #include "dof_manager_default.hh" #if defined(AKANTU_USE_PETSC) #include "dof_manager_petsc.hh" #endif /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ ModelSolver::ModelSolver(Mesh & mesh, const ID & id, UInt memory_id) : Parsable(_st_model_solver, id), SolverCallback(), parent_id(id), parent_memory_id(memory_id), mesh(mesh), dof_manager(NULL), default_solver_id("") {} /* -------------------------------------------------------------------------- */ ModelSolver::~ModelSolver() { delete this->dof_manager; } /* -------------------------------------------------------------------------- */ void ModelSolver::initDOFManager() { std::pair<Parser::const_section_iterator, Parser::const_section_iterator> sub_sect = getStaticParser().getSubSections(_st_model_solver); // default without external solver activated at compilation same as mumps that // is the historical solver but with only the lumped solver ID solver_type = "explicit"; #if defined(AKANTU_USE_MUMPS) solver_type = "mumps"; #elif defined(AKANTU_USE_PETSC) solver_type = "petsc"; #endif const ParserSection * section = NULL; Parser::const_section_iterator it; for (it = sub_sect.first; it != sub_sect.second && section == NULL; ++it) { if (it->getName() == this->parent_id) { section = &(*it); solver_type = section->getOption(solver_type); } } if (section) { this->initDOFManager(*section, solver_type); } else { this->initDOFManager(solver_type); } } /* -------------------------------------------------------------------------- */ void ModelSolver::initDOFManager(const ID & solver_type) { if (solver_type == "explicit") { ID id = this->parent_id + ":dof_manager_default"; this->dof_manager = new DOFManagerDefault(mesh, id, this->parent_memory_id); } else if (solver_type == "petsc") { #if defined(AKANTU_USE_PETSC) ID id = this->parent_id + ":dof_manager_petsc"; this->dof_manager = new DOFManagerPETSc(mesh, id, this->parent_memory_id); #else AKANTU_EXCEPTION( "To use PETSc you have to activate it in the compilations options"); #endif } else if (solver_type == "mumps") { #if defined(AKANTU_USE_MUMPS) ID id = this->parent_id + ":dof_manager_default"; this->dof_manager = new DOFManagerDefault(mesh, id, this->parent_memory_id); #else AKANTU_EXCEPTION( "To use MUMPS you have to activate it in the compilations options"); #endif } else { AKANTU_EXCEPTION( "To use the solver " << solver_type << " you will have to code it. This is an unknown solver type."); } this->setDOFManager(*this->dof_manager); } /* -------------------------------------------------------------------------- */ template <typename T> static T getOptionToType(const std::string & opt_str) { std::stringstream sstr(opt_str); T opt; sstr >> opt; return opt; } /* -------------------------------------------------------------------------- */ void ModelSolver::initDOFManager(const ParserSection & section, const ID & solver_type) { this->initDOFManager(solver_type); std::pair<Parser::const_section_iterator, Parser::const_section_iterator> sub_sect = section.getSubSections(_st_time_step_solver); Parser::const_section_iterator it; for (it = sub_sect.first; it != sub_sect.second; ++it) { ID solver_id = it->getName(); std::string str = it->getOption(); TimeStepSolverType tss_type = it->getParameter("type", this->getDefaultSolverType()); ModelSolverOptions tss_options = this->getDefaultSolverOptions(tss_type); std::pair<Parser::const_section_iterator, Parser::const_section_iterator> sub_solvers_sect = it->getSubSections(_st_non_linear_solver); Parser::const_section_iterator sub_it; UInt nb_non_linear_solver_section = it->getNbSubSections(_st_non_linear_solver); NonLinearSolverType nls_type = tss_options.non_linear_solver_type; if (nb_non_linear_solver_section == 1) { const ParserSection & nls_section = *(sub_solvers_sect.first); nls_type = getOptionToType<NonLinearSolverType>(nls_section.getName()); } else if (nb_non_linear_solver_section > 0) { AKANTU_EXCEPTION("More than one non linear solver are provided for the " "time step solver " << solver_id); } this->getNewSolver(solver_id, tss_type, nls_type); if (nb_non_linear_solver_section == 1) { const ParserSection & nls_section = *(sub_solvers_sect.first); this->dof_manager->getNonLinearSolver(solver_id).parseSection( nls_section); } std::pair<Parser::const_section_iterator, Parser::const_section_iterator> sub_integrator_sect = it->getSubSections(_st_integration_scheme); for (sub_it = sub_integrator_sect.first; sub_it != sub_integrator_sect.second; ++sub_it) { const ParserSection & is_section = *sub_it; const ID & dof_id = is_section.getName(); IntegrationSchemeType it_type = is_section.getParameter( "type", tss_options.integration_scheme_type[dof_id]); IntegrationScheme::SolutionType s_type = is_section.getParameter( "solution_type", tss_options.solution_type[dof_id]); this->setIntegrationScheme(solver_id, dof_id, it_type, s_type); } std::map<ID, IntegrationSchemeType>::const_iterator it = tss_options.integration_scheme_type.begin(); std::map<ID, IntegrationSchemeType>::const_iterator end = tss_options.integration_scheme_type.end(); for (; it != end; ++it) { if (!this->hasIntegrationScheme(solver_id, it->first)) { this->setIntegrationScheme(solver_id, it->first, it->second, tss_options.solution_type[it->first]); } } } if (section.hasParameter("default_solver")) { ID default_solver = section.getParameter("default_solver"); this->setDefaultSolver(default_solver); } } /* -------------------------------------------------------------------------- */ TimeStepSolver & ModelSolver::getSolver(const ID & solver_id) { ID tmp_solver_id = solver_id; if (tmp_solver_id == "") tmp_solver_id = this->default_solver_id; TimeStepSolver & tss = this->dof_manager->getTimeStepSolver(tmp_solver_id); return tss; } /* -------------------------------------------------------------------------- */ const TimeStepSolver & ModelSolver::getSolver(const ID & solver_id) const { ID tmp_solver_id = solver_id; if (solver_id == "") tmp_solver_id = this->default_solver_id; const TimeStepSolver & tss = this->dof_manager->getTimeStepSolver(tmp_solver_id); return tss; } /* -------------------------------------------------------------------------- */ TimeStepSolver & ModelSolver::getTimeStepSolver(const ID & solver_id) { return this->getSolver(solver_id); } /* -------------------------------------------------------------------------- */ const TimeStepSolver & ModelSolver::getTimeStepSolver(const ID & solver_id) const { return this->getSolver(solver_id); } /* -------------------------------------------------------------------------- */ NonLinearSolver & ModelSolver::getNonLinearSolver(const ID & solver_id) { return this->getSolver(solver_id).getNonLinearSolver(); } /* -------------------------------------------------------------------------- */ const NonLinearSolver & ModelSolver::getNonLinearSolver(const ID & solver_id) const { return this->getSolver(solver_id).getNonLinearSolver(); } /* -------------------------------------------------------------------------- */ bool ModelSolver::hasSolver(const ID & solver_id) const { ID tmp_solver_id = solver_id; if (solver_id == "") tmp_solver_id = this->default_solver_id; return this->dof_manager->hasTimeStepSolver(tmp_solver_id); } /* -------------------------------------------------------------------------- */ void ModelSolver::setDefaultSolver(const ID & solver_id) { AKANTU_DEBUG_ASSERT( this->hasSolver(solver_id), "Cannot set the default solver to a solver that does not exists"); this->default_solver_id = solver_id; } /* -------------------------------------------------------------------------- */ void ModelSolver::solveStep(const ID & solver_id) { AKANTU_DEBUG_IN(); TimeStepSolver & tss = this->getSolver(solver_id); // make one non linear solve tss.solveStep(*this); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ModelSolver::getNewSolver(const ID & solver_id, TimeStepSolverType time_step_solver_type, NonLinearSolverType non_linear_solver_type) { if (this->default_solver_id == "") { this->default_solver_id = solver_id; } if (non_linear_solver_type == _nls_auto) { switch (time_step_solver_type) { case _tsst_dynamic: case _tsst_static: non_linear_solver_type = _nls_newton_raphson; break; case _tsst_dynamic_lumped: non_linear_solver_type = _nls_lumped; break; } } this->initSolver(time_step_solver_type, non_linear_solver_type); NonLinearSolver & nls = this->dof_manager->getNewNonLinearSolver( solver_id, non_linear_solver_type); this->dof_manager->getNewTimeStepSolver(solver_id, time_step_solver_type, nls); } /* -------------------------------------------------------------------------- */ Real ModelSolver::getTimeStep(const ID & solver_id) const { const TimeStepSolver & tss = this->getSolver(solver_id); return tss.getTimeStep(); } /* -------------------------------------------------------------------------- */ void ModelSolver::setTimeStep(Real time_step, const ID & solver_id) { TimeStepSolver & tss = this->getSolver(solver_id); return tss.setTimeStep(time_step); } /* -------------------------------------------------------------------------- */ void ModelSolver::setIntegrationScheme( const ID & solver_id, const ID & dof_id, const IntegrationSchemeType & integration_scheme_type, IntegrationScheme::SolutionType solution_type) { TimeStepSolver & tss = this->dof_manager->getTimeStepSolver(solver_id); tss.setIntegrationScheme(dof_id, integration_scheme_type, solution_type); } /* -------------------------------------------------------------------------- */ bool ModelSolver::hasDefaultSolver() const { return (this->default_solver_id != ""); } /* -------------------------------------------------------------------------- */ bool ModelSolver::hasIntegrationScheme(const ID & solver_id, const ID & dof_id) const { TimeStepSolver & tss = this->dof_manager->getTimeStepSolver(solver_id); return tss.hasIntegrationScheme(dof_id); } /* -------------------------------------------------------------------------- */ void ModelSolver::predictor() {} /* -------------------------------------------------------------------------- */ void ModelSolver::corrector() {} /* -------------------------------------------------------------------------- */ TimeStepSolverType ModelSolver::getDefaultSolverType() const { return _tsst_dynamic_lumped; } /* -------------------------------------------------------------------------- */ ModelSolverOptions ModelSolver::getDefaultSolverOptions(__attribute__((unused)) const TimeStepSolverType & type) const { ModelSolverOptions options; options.non_linear_solver_type = _nls_auto; return options; } /* -------------------------------------------------------------------------- */ // void ModelSolver::setIntegrationScheme( // const ID & solver_id, const ID & dof_id, // const IntegrationSchemeType & integration_scheme_type) {} /* -------------------------------------------------------------------------- */ // /* -------------------------------------------------------------------------- // */ // template <NewmarkBeta::IntegrationSchemeCorrectorType type> // void SolidMechanicsModel::solve(Array<Real> &increment, Real block_val, // bool need_factorize, bool // has_profile_changed) { // if(has_profile_changed) { // this->initJacobianMatrix(); // need_factorize = true; // } // updateResidualInternal(); //doesn't do anything for static // if(need_factorize) { // Real c = 0.,d = 0.,e = 0.; // if(method == _static) { // AKANTU_DEBUG_INFO("Solving K inc = r"); // e = 1.; // } else { // AKANTU_DEBUG_INFO("Solving (c M + d C + e K) inc = r"); // NewmarkBeta * nmb_int = dynamic_cast<NewmarkBeta *>(integrator); // c = nmb_int->getAccelerationCoefficient<type>(time_step); // d = nmb_int->getVelocityCoefficient<type>(time_step); // e = nmb_int->getDisplacementCoefficient<type>(time_step); // } // jacobian_matrix->clear(); // // J = c M + d C + e K // if(stiffness_matrix) // jacobian_matrix->add(*stiffness_matrix, e); // if(mass_matrix) // jacobian_matrix->add(*mass_matrix, c); // #if !defined(AKANTU_NDEBUG) // if(mass_matrix && AKANTU_DEBUG_TEST(dblDump)) // mass_matrix->saveMatrix("M.mtx"); // #endif // if(velocity_damping_matrix) // jacobian_matrix->add(*velocity_damping_matrix, d); // jacobian_matrix->applyBoundary(*blocked_dofs, block_val); // #if !defined(AKANTU_NDEBUG) // if(AKANTU_DEBUG_TEST(dblDump)) // jacobian_matrix->saveMatrix("J.mtx"); // #endif // solver->factorize(); // } // // if (rhs.getSize() != 0) // // solver->setRHS(rhs); // // else // solver->setOperators(); // solver->setRHS(*residual); // // solve @f[ J \delta w = r @f] // solver->solve(increment); // UInt nb_nodes = displacement-> getSize(); // UInt nb_degree_of_freedom = displacement->getNbComponent() * nb_nodes; // bool * blocked_dofs_val = blocked_dofs->storage(); // Real * increment_val = increment.storage(); // for (UInt j = 0; j < nb_degree_of_freedom; // ++j,++increment_val, ++blocked_dofs_val) { // if ((*blocked_dofs_val)) // *increment_val = 0.0; // } // } // /* -------------------------------------------------------------------------- // */ // template<SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria> // bool SolidMechanicsModel::solveStatic(Real tolerance, UInt max_iteration, // bool do_not_factorize) { // AKANTU_DEBUG_INFO("Solving Ku = f"); // AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL, // "You should first initialize the implicit solver and // assemble the stiffness matrix by calling // initImplicit"); // AnalysisMethod analysis_method=method; // Real error = 0.; // method=_static; // bool converged = this->template solveStep<cmethod, criteria>(tolerance, // error, max_iteration, do_not_factorize); // method=analysis_method; // return converged; // } // /* -------------------------------------------------------------------------- // */ // template<SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria> // bool SolidMechanicsModel::solveStep(Real tolerance, // UInt max_iteration) { // Real error = 0.; // return this->template solveStep<cmethod,criteria>(tolerance, // error, // max_iteration); // } // /* -------------------------------------------------------------------------- // */ // template<SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria> // bool SolidMechanicsModel::solveStep(Real tolerance, Real & error, UInt // max_iteration, // bool do_not_factorize) { // EventManager::sendEvent(SolidMechanicsModelEvent::BeforeSolveStepEvent(method)); // this->implicitPred(); // this->updateResidual(); // AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL, // "You should first initialize the implicit solver and // assemble the stiffness matrix"); // bool need_factorize = !do_not_factorize; // if (method==_implicit_dynamic) { // AKANTU_DEBUG_ASSERT(mass_matrix != NULL, // "You should first initialize the implicit solver and // assemble the mass matrix"); // } // switch (cmethod) { // case _scm_newton_raphson_tangent: // case _scm_newton_raphson_tangent_not_computed: // break; // case _scm_newton_raphson_tangent_modified: // this->assembleStiffnessMatrix(); // break; // default: // AKANTU_DEBUG_ERROR("The resolution method " << cmethod << " has not been // implemented!"); // } // this->n_iter = 0; // bool converged = false; // error = 0.; // if(criteria == _scc_residual) { // converged = this->testConvergence<criteria> (tolerance, error); // if(converged) return converged; // } // do { // if (cmethod == _scm_newton_raphson_tangent) // this->assembleStiffnessMatrix(); // solve<NewmarkBeta::_displacement_corrector> (*increment, 1., // need_factorize); // this->implicitCorr(); // if(criteria == _scc_residual) this->updateResidual(); // converged = this->testConvergence<criteria> (tolerance, error); // if(criteria == _scc_increment && !converged) this->updateResidual(); // //this->dump(); // this->n_iter++; // AKANTU_DEBUG_INFO("[" << criteria << "] Convergence iteration " // << std::setw(std::log10(max_iteration)) << this->n_iter // << ": error " << error << (converged ? " < " : " > ") // << tolerance); // switch (cmethod) { // case _scm_newton_raphson_tangent: // need_factorize = true; // break; // case _scm_newton_raphson_tangent_not_computed: // case _scm_newton_raphson_tangent_modified: // need_factorize = false; // break; // default: // AKANTU_DEBUG_ERROR("The resolution method " << cmethod << " has not // been implemented!"); // } // } while (!converged && this->n_iter < max_iteration); // // this makes sure that you have correct strains and stresses after the // solveStep function (e.g., for dumping) // if(criteria == _scc_increment) this->updateResidual(); // if (converged) { // EventManager::sendEvent(SolidMechanicsModelEvent::AfterSolveStepEvent(method)); // } else if(this->n_iter == max_iteration) { // AKANTU_DEBUG_WARNING("[" << criteria << "] Convergence not reached after // " // << std::setw(std::log10(max_iteration)) << // this->n_iter << // " iteration" << (this->n_iter == 1 ? "" : "s") << // "!" << std::endl); // } // return converged; // } // void SolidMechanicsModel::updateResidualInternal() { // AKANTU_DEBUG_IN(); // AKANTU_DEBUG_INFO("Update the residual"); // // f = f_ext - f_int - Ma - Cv = r - Ma - Cv; // if(method != _static) { // // f -= Ma // if(mass_matrix) { // // if full mass_matrix // Array<Real> * Ma = new Array<Real>(*acceleration, true, "Ma"); // *Ma *= *mass_matrix; // /// \todo check unit conversion for implicit dynamics // // *Ma /= f_m2a // *residual -= *Ma; // delete Ma; // } else if (mass) { // // else lumped mass // UInt nb_nodes = acceleration->getSize(); // UInt nb_degree_of_freedom = acceleration->getNbComponent(); // Real * mass_val = mass->storage(); // Real * accel_val = acceleration->storage(); // Real * res_val = residual->storage(); // bool * blocked_dofs_val = blocked_dofs->storage(); // for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) { // if(!(*blocked_dofs_val)) { // *res_val -= *accel_val * *mass_val /f_m2a; // } // blocked_dofs_val++; // res_val++; // mass_val++; // accel_val++; // } // } else { // AKANTU_DEBUG_ERROR("No function called to assemble the mass matrix."); // } // // f -= Cv // if(velocity_damping_matrix) { // Array<Real> * Cv = new Array<Real>(*velocity); // *Cv *= *velocity_damping_matrix; // *residual -= *Cv; // delete Cv; // } // } // AKANTU_DEBUG_OUT(); // } // /* -------------------------------------------------------------------------- // */ // void SolidMechanicsModel::solveLumped(Array<Real> & x, // const Array<Real> & A, // const Array<Real> & b, // const Array<bool> & blocked_dofs, // Real alpha) { // Real * A_val = A.storage(); // Real * b_val = b.storage(); // Real * x_val = x.storage(); // bool * blocked_dofs_val = blocked_dofs.storage(); // UInt nb_degrees_of_freedom = x.getSize() * x.getNbComponent(); // for (UInt n = 0; n < nb_degrees_of_freedom; ++n) { // if(!(*blocked_dofs_val)) { // *x_val = alpha * (*b_val / *A_val); // } // x_val++; // A_val++; // b_val++; // blocked_dofs_val++; // } // } /* -------------------------------------------------------------------------- */ // void TimeStepSolverDefault::updateAcceleration() { // AKANTU_DEBUG_IN(); // updateResidualInternal(); // if (method == _explicit_lumped_mass) { // /* residual = residual_{n+1} - M * acceleration_n therefore // solution = increment acceleration not acceleration */ // solveLumped(*increment_acceleration, *mass, *residual, *blocked_dofs, // f_m2a); // } else if (method == _explicit_consistent_mass) { // solve<NewmarkBeta::_acceleration_corrector>(*increment_acceleration); // } // AKANTU_DEBUG_OUT(); // } -__END_AKANTU__ +} // akantu diff --git a/src/model/model_solver.hh b/src/model/model_solver.hh index 1bbcf8629..27dd227f5 100644 --- a/src/model/model_solver.hh +++ b/src/model/model_solver.hh @@ -1,191 +1,191 @@ /** * @file model_solver.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Wed Jul 22 10:53:10 2015 * * @brief Class regrouping the common solve interface to the different models * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "integration_scheme.hh" #include "parsable.hh" #include "solver_callback.hh" #include "synchronizer_registry.hh" /* -------------------------------------------------------------------------- */ #include <set> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MODEL_SOLVER_HH__ #define __AKANTU_MODEL_SOLVER_HH__ namespace akantu { class Mesh; class DOFManager; class TimeStepSolver; class NonLinearSolver; struct ModelSolverOptions; } -__BEGIN_AKANTU__ +namespace akantu { class ModelSolver : public Parsable, public SolverCallback, public SynchronizerRegistry { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ModelSolver(Mesh & mesh, const ID & id, UInt memory_id); virtual ~ModelSolver(); /// initialize the dof manager based on solver type passed in the input file void initDOFManager(); /// initialize the dof manager based on the used chosen solver type void initDOFManager(const ID & solver_type); protected: /// initialize the dof manager based on the used chosen solver type void initDOFManager(const ParserSection & section, const ID & solver_type); /// Callback for the model to instantiate the matricees when needed virtual void initSolver(__attribute__((unused)) TimeStepSolverType time_step_solver_type, __attribute__((unused)) NonLinearSolverType non_linear_solver_type) { } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// solve a step using a given pre instantiated time step solver and /// nondynamic linear solver void solveStep(const ID & solver_id = ""); /// Initialize a time solver that can be used afterwards with its id void getNewSolver(const ID & solver_id, TimeStepSolverType time_step_solver_type, NonLinearSolverType non_linear_solver_type = _nls_auto); /// set an integration scheme for a given dof and a given solver void setIntegrationScheme(const ID & solver_id, const ID & dof_id, const IntegrationSchemeType & integration_scheme_type, IntegrationScheme::SolutionType solution_type = IntegrationScheme::_not_defined); /// set an externally instantiated integration scheme void setIntegrationScheme(const ID & solver_id, const ID & dof_id, IntegrationScheme & integration_scheme, IntegrationScheme::SolutionType solution_type = IntegrationScheme::_not_defined); /* ------------------------------------------------------------------------ */ /* SolverCallback interface */ /* ------------------------------------------------------------------------ */ public: /// Predictor interface for the callback virtual void predictor(); /// Corrector interface for the callback virtual void corrector(); /// AssembleResidual interface for the callback virtual void assembleResidual() = 0; /// AssembleJacobian interface for the callback virtual void assembleJacobian() = 0; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// Default time step solver to instantiate for this model virtual TimeStepSolverType getDefaultSolverType() const; /// Default configurations for a given time step solver virtual ModelSolverOptions getDefaultSolverOptions(const TimeStepSolverType & type) const; /// get access to the internal dof manager DOFManager & getDOFManager() { return *this->dof_manager; } /// get the time step of a given solver Real getTimeStep(const ID & solver_id = "") const; /// set the time step of a given solver virtual void setTimeStep(Real time_step, const ID & solver_id = ""); /// set the parameter 'param' of the solver 'solver_id' template <typename T> void set(const ID & param, const T & value, const ID & solver_id = ""); /// get the parameter 'param' of the solver 'solver_id' const Parameter & get(const ID & param, const ID & solver_id = "") const; /// answer to the question "does the solver exists ?" bool hasSolver(const ID & solver_id) const; /// changes the current default solver void setDefaultSolver(const ID & solver_id); /// is a default solver defined bool hasDefaultSolver() const; /// is an integration scheme set for a given solver and a given dof bool hasIntegrationScheme(const ID & solver_id, const ID & dof_id) const; TimeStepSolver & getTimeStepSolver(const ID & solver_id = ""); NonLinearSolver & getNonLinearSolver(const ID & solver_id = ""); const TimeStepSolver & getTimeStepSolver(const ID & solver_id = "") const; const NonLinearSolver & getNonLinearSolver(const ID & solver_id = "") const; private: TimeStepSolver & getSolver(const ID & solver_id); const TimeStepSolver & getSolver(const ID & solver_id) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: ID parent_id; UInt parent_memory_id; /// Underlying mesh Mesh & mesh; /// Underlying dof_manager (the brain...) DOFManager * dof_manager; /// Default time step solver to use ID default_solver_id; }; struct ModelSolverOptions { NonLinearSolverType non_linear_solver_type; std::map<ID, IntegrationSchemeType> integration_scheme_type; std::map<ID, IntegrationScheme::SolutionType> solution_type; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MODEL_SOLVER_HH__ */ diff --git a/src/model/model_solver_tmpl.hh b/src/model/model_solver_tmpl.hh index c351fcc17..3294541e2 100644 --- a/src/model/model_solver_tmpl.hh +++ b/src/model/model_solver_tmpl.hh @@ -1,54 +1,54 @@ /** * @file model_solver_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Fri Apr 29 17:16:33 2016 * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "time_step_solver.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MODEL_SOLVER_TMPL_HH__ #define __AKANTU_MODEL_SOLVER_TMPL_HH__ -__BEGIN_AKANTU__ +namespace akantu { template<typename T> void ModelSolver::set(const ID & param, const T & value, const ID & solver_id) { TimeStepSolver & solver = this->getSolver(solver_id); solver.setParam(param, value); } inline Parameter ModelSolver::get(const ID & param, const ID & solver_id) { TimeStepSolver & solver = this->getSolver(solver_id); return solver.getParam(param); } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MODEL_SOLVER_TMPL_HH__ */ diff --git a/src/model/non_linear_solver.cc b/src/model/non_linear_solver.cc index 3dd79dedb..a970e4210 100644 --- a/src/model/non_linear_solver.cc +++ b/src/model/non_linear_solver.cc @@ -1,66 +1,66 @@ /** * @file non_linear_solver.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Tue Oct 13 15:34:43 2015 * * @brief Implementation of the base class NonLinearSolver * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "non_linear_solver.hh" #include "solver_callback.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ NonLinearSolver::NonLinearSolver( DOFManager & dof_manager, const NonLinearSolverType & non_linear_solver_type, const ID & id, UInt memory_id) : Memory(id, memory_id), Parsable(_st_non_linear_solver, id), _dof_manager(dof_manager), non_linear_solver_type(non_linear_solver_type) { this->registerParam("type", this->non_linear_solver_type, _pat_parsable, "Non linear solver type"); } /* -------------------------------------------------------------------------- */ NonLinearSolver::~NonLinearSolver() {} /* -------------------------------------------------------------------------- */ void NonLinearSolver::checkIfTypeIsSupported() { if (this->supported_type.find(this->non_linear_solver_type) == this->supported_type.end()) { AKANTU_EXCEPTION("The resolution method " << this->non_linear_solver_type << " is not implemented in the non linear solver " << this->id << "!"); } } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/non_linear_solver.hh b/src/model/non_linear_solver.hh index 616fa6a52..750e0536d 100644 --- a/src/model/non_linear_solver.hh +++ b/src/model/non_linear_solver.hh @@ -1,96 +1,96 @@ /** * @file non_linear_solver.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Mon Aug 24 23:48:41 2015 * * @brief Non linear solver interface * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "parsable.hh" /* -------------------------------------------------------------------------- */ #include <set> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NON_LINEAR_SOLVER_HH__ #define __AKANTU_NON_LINEAR_SOLVER_HH__ namespace akantu { class DOFManager; class SolverCallback; } -__BEGIN_AKANTU__ +namespace akantu { class NonLinearSolver : Memory, public Parsable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NonLinearSolver(DOFManager & dof_manager, const NonLinearSolverType & non_linear_solver_type, const ID & id = "non_linear_solver", UInt memory_id = 0); virtual ~NonLinearSolver(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// solve the system described by the jacobian matrix, and rhs contained in /// the dof manager virtual void solve(SolverCallback & callback) = 0; protected: void checkIfTypeIsSupported(); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: DOFManager & _dof_manager; /// type of non linear solver NonLinearSolverType non_linear_solver_type; /// list of supported non linear solver types std::set<NonLinearSolverType> supported_type; }; namespace debug { class NLSNotConvergedException : public Exception { public: NLSNotConvergedException(Real threshold, UInt niter, Real error) : Exception("The non linear solver did not converge."), threshold(threshold), niter(niter), error(error) {} Real threshold; UInt niter; Real error; }; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_NON_LINEAR_SOLVER_HH__ */ diff --git a/src/model/non_linear_solver_callback.hh b/src/model/non_linear_solver_callback.hh index c9a393af6..9c1950aa4 100644 --- a/src/model/non_linear_solver_callback.hh +++ b/src/model/non_linear_solver_callback.hh @@ -1,61 +1,61 @@ /** * @file non_linear_solver_callback.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Mon Sep 28 18:48:21 2015 * * @brief Interface to implement for the non linear solver to work * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NON_LINEAR_SOLVER_CALLBACK_HH__ #define __AKANTU_NON_LINEAR_SOLVER_CALLBACK_HH__ -__BEGIN_AKANTU__ +namespace akantu { class NonLinearSolverCallback { /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// callback to assemble the Jacobian Matrix virtual void assembleJacobian() { AKANTU_DEBUG_TO_IMPLEMENT(); } /// callback to assemble the residual (rhs) virtual void assembleResidual() { AKANTU_DEBUG_TO_IMPLEMENT(); } /* ------------------------------------------------------------------------ */ /* Dynamic simulations part */ /* ------------------------------------------------------------------------ */ /// callback for the predictor (in case of dynamic simulation) virtual void predictor() { AKANTU_DEBUG_TO_IMPLEMENT(); } /// callback for the corrector (in case of dynamic simulation) virtual void corrector() { AKANTU_DEBUG_TO_IMPLEMENT(); } }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_NON_LINEAR_SOLVER_CALLBACK_HH__ */ diff --git a/src/model/non_linear_solver_linear.cc b/src/model/non_linear_solver_linear.cc index 8b518193c..fd10e5b2f 100644 --- a/src/model/non_linear_solver_linear.cc +++ b/src/model/non_linear_solver_linear.cc @@ -1,71 +1,71 @@ /** * @file non_linear_solver_linear.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Tue Aug 25 00:57:00 2015 * * @brief Implementation of the default NonLinearSolver * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "non_linear_solver_linear.hh" #include "dof_manager_default.hh" #include "solver_callback.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ NonLinearSolverLinear::NonLinearSolverLinear( DOFManagerDefault & dof_manager, const NonLinearSolverType & non_linear_solver_type, const ID & id, UInt memory_id) : NonLinearSolver(dof_manager, non_linear_solver_type, id, memory_id), dof_manager(dof_manager), solver(dof_manager, "J", id + ":sparse_solver", memory_id) { this->supported_type.insert(_nls_linear); this->checkIfTypeIsSupported(); } /* -------------------------------------------------------------------------- */ NonLinearSolverLinear::~NonLinearSolverLinear() {} /* ------------------------------------------------------------------------ */ void NonLinearSolverLinear::solve(SolverCallback & solver_callback) { this->dof_manager.updateGlobalBlockedDofs(); solver_callback.predictor(); solver_callback.assembleResidual(); solver_callback.assembleJacobian(); this->solver.solve(); solver_callback.corrector(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/non_linear_solver_linear.hh b/src/model/non_linear_solver_linear.hh index 09f8b2915..c52b5a693 100644 --- a/src/model/non_linear_solver_linear.hh +++ b/src/model/non_linear_solver_linear.hh @@ -1,78 +1,78 @@ /** * @file non_linear_solver_linear.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Tue Aug 25 00:48:07 2015 * * @brief Default implementation of NonLinearSolver, in case no external library * is there to do the job * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "non_linear_solver.hh" #include "sparse_solver_mumps.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NON_LINEAR_SOLVER_LINEAR_HH__ #define __AKANTU_NON_LINEAR_SOLVER_LINEAR_HH__ namespace akantu { class DOFManagerDefault; } -__BEGIN_AKANTU__ +namespace akantu { class NonLinearSolverLinear : public NonLinearSolver { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NonLinearSolverLinear(DOFManagerDefault & dof_manager, const NonLinearSolverType & non_linear_solver_type, const ID & id = "non_linear_solver_linear", UInt memory_id = 0); virtual ~NonLinearSolverLinear(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// Function that solve the non linear system described by the dof manager and /// the solver callback functions virtual void solve(SolverCallback & solver_callback); AKANTU_GET_MACRO_NOT_CONST(Solver, solver, SparseSolverMumps &); AKANTU_GET_MACRO(Solver, solver, const SparseSolverMumps &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: DOFManagerDefault & dof_manager; /// Sparse solver used for the linear solves SparseSolverMumps solver; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_NON_LINEAR_SOLVER_LINEAR_HH__ */ diff --git a/src/model/non_linear_solver_lumped.cc b/src/model/non_linear_solver_lumped.cc index 7fc359883..5b3a89f80 100644 --- a/src/model/non_linear_solver_lumped.cc +++ b/src/model/non_linear_solver_lumped.cc @@ -1,103 +1,103 @@ /** * @file non_linear_solver_lumped.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Tue Aug 25 00:57:00 2015 * * @brief Implementation of the default NonLinearSolver * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "non_linear_solver_lumped.hh" #include "dof_manager_default.hh" #include "solver_callback.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ NonLinearSolverLumped::NonLinearSolverLumped( DOFManagerDefault & dof_manager, const NonLinearSolverType & non_linear_solver_type, const ID & id, UInt memory_id) : NonLinearSolver(dof_manager, non_linear_solver_type, id, memory_id), dof_manager(dof_manager) { this->supported_type.insert(_nls_lumped); this->checkIfTypeIsSupported(); this->registerParam("b_a2x", this->alpha, 1., _pat_parsmod, "Conversion coefficient between x and A^{-1} b"); } /* -------------------------------------------------------------------------- */ NonLinearSolverLumped::~NonLinearSolverLumped() {} /* ------------------------------------------------------------------------ */ void NonLinearSolverLumped::solve(SolverCallback & solver_callback) { this->dof_manager.updateGlobalBlockedDofs(); solver_callback.predictor(); const Array<Real> & A = this->dof_manager.getLumpedMatrix("M"); Array<Real> & x = this->dof_manager.getGlobalSolution(); const Array<Real> & b = this->dof_manager.getResidual(); x.resize(b.getSize()); this->dof_manager.updateGlobalBlockedDofs(); const Array<bool> & blocked_dofs = this->dof_manager.getGlobalBlockedDOFs(); solver_callback.assembleResidual(); // alpha is the conversion factor from from force/mass to acceleration needed // in model coupled with atomistic \todo find a way to define alpha per dof // type this->solveLumped(A, x, b, blocked_dofs, alpha); this->dof_manager.splitSolutionPerDOFs(); solver_callback.corrector(); } /* -------------------------------------------------------------------------- */ void NonLinearSolverLumped::solveLumped(const Array<Real> & A, Array<Real> & x, const Array<Real> & b, const Array<bool> & blocked_dofs, Real alpha) { Array<Real>::const_scalar_iterator A_it = A.begin(); Array<Real>::scalar_iterator x_it = x.begin(); Array<Real>::scalar_iterator x_end = x.end(); Array<Real>::const_scalar_iterator b_it = b.begin(); Array<bool>::const_scalar_iterator blocked_it = blocked_dofs.begin(); for (; x_it != x_end; ++x_it, ++b_it, ++A_it, ++blocked_it) { if (!(*blocked_it)) { *x_it = alpha *(*b_it / *A_it); } } } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/non_linear_solver_lumped.hh b/src/model/non_linear_solver_lumped.hh index 03ec67c44..834791c3c 100644 --- a/src/model/non_linear_solver_lumped.hh +++ b/src/model/non_linear_solver_lumped.hh @@ -1,82 +1,82 @@ /** * @file non_linear_solver_lumped.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Tue Aug 25 00:48:07 2015 * * @brief Default implementation of NonLinearSolver, in case no external library * is there to do the job * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "non_linear_solver.hh" #include "sparse_solver_mumps.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NON_LINEAR_SOLVER_LUMPED_HH__ #define __AKANTU_NON_LINEAR_SOLVER_LUMPED_HH__ namespace akantu { class DOFManagerDefault; } -__BEGIN_AKANTU__ +namespace akantu { class NonLinearSolverLumped : public NonLinearSolver { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NonLinearSolverLumped(DOFManagerDefault & dof_manager, const NonLinearSolverType & non_linear_solver_type, const ID & id = "non_linear_solver_lumped", UInt memory_id = 0); virtual ~NonLinearSolverLumped(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// Function that solve the non linear system described by the dof manager and /// the solver callback functions virtual void solve(SolverCallback & solver_callback); static void solveLumped(const Array<Real> & A, Array<Real> & x, const Array<Real> & b, const Array<bool> & blocked_dofs, Real alpha); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: DOFManagerDefault & dof_manager; /// Coefficient to apply between x and A^{-1} b Real alpha; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_NON_LINEAR_SOLVER_LUMPED_HH__ */ diff --git a/src/model/non_linear_solver_newton_raphson.cc b/src/model/non_linear_solver_newton_raphson.cc index 59a5d6c1f..c2fb7ba4a 100644 --- a/src/model/non_linear_solver_newton_raphson.cc +++ b/src/model/non_linear_solver_newton_raphson.cc @@ -1,186 +1,186 @@ /** * @file non_linear_solver_newton_raphson.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Tue Aug 25 00:57:00 2015 * * @brief Implementation of the default NonLinearSolver * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "non_linear_solver_newton_raphson.hh" #include "dof_manager_default.hh" #include "solver_callback.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ NonLinearSolverNewtonRaphson::NonLinearSolverNewtonRaphson( DOFManagerDefault & dof_manager, const NonLinearSolverType & non_linear_solver_type, const ID & id, UInt memory_id) : NonLinearSolver(dof_manager, non_linear_solver_type, id, memory_id), dof_manager(dof_manager), solver(dof_manager, "J", id + ":sparse_solver", memory_id), n_iter(0), error(0.), converged(false) { this->supported_type.insert(_nls_newton_raphson_modified); this->supported_type.insert(_nls_newton_raphson); this->supported_type.insert(_nls_linear); this->checkIfTypeIsSupported(); this->registerParam("threshold", convergence_criteria, 1e-10, _pat_parsmod, "Threshold to consider results as converged"); this->registerParam("convergence_type", convergence_criteria_type, _scc_solution, _pat_parsmod, "Type of convergence criteria"); this->registerParam("max_iterations", max_iterations, 10, _pat_parsmod, "Max number of iterations"); this->registerParam("error", error, _pat_readable, "Last reached error"); this->registerParam("nb_iterations", n_iter, _pat_readable, "Last reached number of iterations"); this->registerParam("converged", converged, _pat_readable, "Did last solve converged"); this->registerParam("force_linear_recompute", force_linear_recompute, true, _pat_modifiable, "Force reassembly of the jacobian matrix"); } /* -------------------------------------------------------------------------- */ NonLinearSolverNewtonRaphson::~NonLinearSolverNewtonRaphson() {} /* ------------------------------------------------------------------------ */ void NonLinearSolverNewtonRaphson::solve(SolverCallback & solver_callback) { this->dof_manager.updateGlobalBlockedDofs(); solver_callback.predictor(); solver_callback.assembleResidual(); if (this->non_linear_solver_type == _nls_newton_raphson_modified || (this->non_linear_solver_type == _nls_linear && this->force_linear_recompute)) { solver_callback.assembleJacobian(); this->force_linear_recompute = false; } this->n_iter = 0; this->converged = false; if (this->convergence_criteria_type == _scc_residual) { this->converged = this->testConvergence(this->dof_manager.getResidual()); if (this->converged) return; } do { if (this->non_linear_solver_type == _nls_newton_raphson) solver_callback.assembleJacobian(); this->solver.solve(); solver_callback.corrector(); // EventManager::sendEvent(NonLinearSolver::AfterSparseSolve(method)); if (this->convergence_criteria_type == _scc_residual) { solver_callback.assembleResidual(); this->converged = this->testConvergence(this->dof_manager.getResidual()); } else { this->converged = this->testConvergence(this->dof_manager.getGlobalSolution()); } if (this->convergence_criteria_type == _scc_solution && !this->converged) solver_callback.assembleResidual(); // this->dump(); this->n_iter++; AKANTU_DEBUG_INFO( "[" << this->convergence_criteria_type << "] Convergence iteration " << std::setw(std::log10(this->max_iterations)) << this->n_iter << ": error " << this->error << (this->converged ? " < " : " > ") << this->convergence_criteria); } while (!this->converged && this->n_iter < this->max_iterations); // this makes sure that you have correct strains and stresses after the // solveStep function (e.g., for dumping) if (this->convergence_criteria_type == _scc_solution) solver_callback.assembleResidual(); if (this->converged) { // EventManager::sendEvent( // SolidMechanicsModelEvent::AfterNonLinearSolverSolves(method)); } else if (this->n_iter == this->max_iterations) { AKANTU_CUSTOM_EXCEPTION(debug::NLSNotConvergedException( this->convergence_criteria, this->n_iter, this->error)); AKANTU_DEBUG_WARNING("[" << this->convergence_criteria_type << "] Convergence not reached after " << std::setw(std::log10(this->max_iterations)) << this->n_iter << " iteration" << (this->n_iter == 1 ? "" : "s") << "!"); } return; } /* -------------------------------------------------------------------------- */ bool NonLinearSolverNewtonRaphson::testConvergence(const Array<Real> & array) { AKANTU_DEBUG_IN(); const Array<bool> & blocked_dofs = this->dof_manager.getGlobalBlockedDOFs(); UInt nb_degree_of_freedoms = array.getSize(); auto arr_it = array.begin(); auto bld_it = blocked_dofs.begin(); Real norm = 0.; for (UInt n = 0; n < nb_degree_of_freedoms; ++n, ++arr_it, ++bld_it) { bool is_local_node = this->dof_manager.isLocalOrMasterDOF(n); if ((! *bld_it) && is_local_node) { norm += *arr_it * *arr_it; } } StaticCommunicator::getStaticCommunicator().allReduce(norm, _so_sum); norm = std::sqrt(norm); AKANTU_DEBUG_ASSERT(!Math::isnan(norm), "Something went wrong in the solve phase"); this->error = norm; return (error < this->convergence_criteria); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/non_linear_solver_newton_raphson.hh b/src/model/non_linear_solver_newton_raphson.hh index 7faf40241..1b07a299d 100644 --- a/src/model/non_linear_solver_newton_raphson.hh +++ b/src/model/non_linear_solver_newton_raphson.hh @@ -1,104 +1,104 @@ /** * @file non_linear_solver_newton_raphson.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Tue Aug 25 00:48:07 2015 * * @brief Default implementation of NonLinearSolver, in case no external library * is there to do the job * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "non_linear_solver.hh" #include "sparse_solver_mumps.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NON_LINEAR_SOLVER_NEWTON_RAPHSON_HH__ #define __AKANTU_NON_LINEAR_SOLVER_NEWTON_RAPHSON_HH__ namespace akantu { class DOFManagerDefault; } -__BEGIN_AKANTU__ +namespace akantu { class NonLinearSolverNewtonRaphson : public NonLinearSolver { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NonLinearSolverNewtonRaphson(DOFManagerDefault & dof_manager, const NonLinearSolverType & non_linear_solver_type, const ID & id = "non_linear_solver_newton_raphson", UInt memory_id = 0); virtual ~NonLinearSolverNewtonRaphson(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// Function that solve the non linear system described by the dof manager and /// the solver callback functions virtual void solve(SolverCallback & solver_callback); AKANTU_GET_MACRO_NOT_CONST(Solver, solver, SparseSolverMumps &); AKANTU_GET_MACRO(Solver, solver, const SparseSolverMumps &); protected: /// test the convergence compare norm of array to convergence_criteria bool testConvergence(const Array<Real> & array); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: DOFManagerDefault & dof_manager; /// Sparse solver used for the linear solves SparseSolverMumps solver; /// Type of convergence criteria SolveConvergenceCriteria convergence_criteria_type; /// convergence threshold Real convergence_criteria; /// Max number of iterations int max_iterations; /// Number of iterations at last solve call int n_iter; /// Convergence error at last solve call Real error; /// Did the last call to solve reached convergence bool converged; /// Force a re-computation of the jacobian matrix bool force_linear_recompute; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_NON_LINEAR_SOLVER_NEWTON_RAPHSON_HH__ */ diff --git a/src/model/solid_mechanics/material.cc b/src/model/solid_mechanics/material.cc index 7dc88bfd3..01f28e949 100644 --- a/src/model/solid_mechanics/material.cc +++ b/src/model/solid_mechanics/material.cc @@ -1,1628 +1,1628 @@ /** * @file material.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue Jul 27 2010 * @date last modification: Tue Nov 24 2015 * * @brief Implementation of the common part of the material class * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ Material::Material(SolidMechanicsModel & model, const ID & id) : Memory(id, model.getMemoryID()), Parsable(_st_material, id), is_init(false), fem(&(model.getFEEngine())), finite_deformation(false), name(""), model(&model), spatial_dimension(this->model->getSpatialDimension()), element_filter("element_filter", id, this->memory_id), stress("stress", *this), eigengradu("eigen_grad_u", *this), gradu("grad_u", *this), green_strain("green_strain", *this), piola_kirchhoff_2("piola_kirchhoff_2", *this), potential_energy("potential_energy", *this), is_non_local(false), use_previous_stress(false), use_previous_gradu(false), interpolation_inverse_coordinates("interpolation inverse coordinates", *this), interpolation_points_matrices("interpolation points matrices", *this) { AKANTU_DEBUG_IN(); /// for each connectivity types allocate the element filer array of the /// material model.getMesh().initElementTypeMapArray(element_filter, 1, spatial_dimension, false, _ek_regular); this->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Material::Material(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id) : Memory(id, model.getMemoryID()), Parsable(_st_material, id), is_init(false), fem(&(model.getFEEngine())), finite_deformation(false), name(""), model(&model), spatial_dimension(dim), element_filter("element_filter", id, this->memory_id), stress("stress", *this, dim, fe_engine, this->element_filter), eigengradu("eigen_grad_u", *this, dim, fe_engine, this->element_filter), gradu("gradu", *this, dim, fe_engine, this->element_filter), green_strain("green_strain", *this, dim, fe_engine, this->element_filter), piola_kirchhoff_2("poila_kirchhoff_2", *this, dim, fe_engine, this->element_filter), potential_energy("potential_energy", *this, dim, fe_engine, this->element_filter), is_non_local(false), use_previous_stress(false), use_previous_gradu(false), interpolation_inverse_coordinates("interpolation inverse_coordinates", *this, dim, fe_engine, this->element_filter), interpolation_points_matrices("interpolation points matrices", *this, dim, fe_engine, this->element_filter) { AKANTU_DEBUG_IN(); mesh.initElementTypeMapArray(element_filter, 1, spatial_dimension, false, _ek_regular); this->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Material::~Material() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::initialize() { registerParam("rho", rho, Real(0.), _pat_parsable | _pat_modifiable, "Density"); registerParam("name", name, std::string(), _pat_parsable | _pat_readable); registerParam("finite_deformation", finite_deformation, false, _pat_parsable | _pat_readable, "Is finite deformation"); registerParam("inelastic_deformation", inelastic_deformation, false, _pat_internal, "Is inelastic deformation"); /// allocate gradu stress for local elements eigengradu.initialize(spatial_dimension * spatial_dimension); gradu.initialize(spatial_dimension * spatial_dimension); stress.initialize(spatial_dimension * spatial_dimension); potential_energy.initialize(1); this->model->registerEventHandler(*this); } /* -------------------------------------------------------------------------- */ void Material::initMaterial() { AKANTU_DEBUG_IN(); if (finite_deformation) { this->piola_kirchhoff_2.initialize(spatial_dimension * spatial_dimension); if (use_previous_stress) this->piola_kirchhoff_2.initializeHistory(); this->green_strain.initialize(spatial_dimension * spatial_dimension); } if (use_previous_stress) this->stress.initializeHistory(); if (use_previous_gradu) this->gradu.initializeHistory(); for (std::map<ID, InternalField<Real> *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->resize(); for (std::map<ID, InternalField<UInt> *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->resize(); for (std::map<ID, InternalField<bool> *>::iterator it = internal_vectors_bool.begin(); it != internal_vectors_bool.end(); ++it) it->second->resize(); is_init = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::savePreviousState() { AKANTU_DEBUG_IN(); for (std::map<ID, InternalField<Real> *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) { if (it->second->hasHistory()) it->second->saveCurrentValues(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Compute the residual by assembling @f$\int_{e} \sigma_e \frac{\partial * \varphi}{\partial X} dX @f$ * * @param[in] displacements nodes displacements * @param[in] ghost_type compute the residual for _ghost or _not_ghost element */ // void Material::updateResidual(GhostType ghost_type) { // AKANTU_DEBUG_IN(); // computeAllStresses(ghost_type); // assembleResidual(ghost_type); // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ void Material::assembleInternalForces(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); if (!finite_deformation) { Array<Real> & internal_force = const_cast<Array<Real> &>(model->getInternalForce()); Mesh & mesh = fem->getMesh(); Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension, ghost_type); for (; it != last_type; ++it) { Array<UInt> & elem_filter = element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element) { const Array<Real> & shapes_derivatives = fem->getShapesDerivatives(*it, ghost_type); UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); UInt nb_quadrature_points = fem->getNbIntegrationPoints(*it, ghost_type); /// compute @f$\sigma \frac{\partial \varphi}{\partial X}@f$ by /// @f$\mathbf{B}^t \mathbf{\sigma}_q@f$ Array<Real> * sigma_dphi_dx = new Array<Real>(nb_element * nb_quadrature_points, size_of_shapes_derivatives, "sigma_x_dphi_/_dX"); Array<Real> * shapesd_filtered = new Array<Real>(0, size_of_shapes_derivatives, "filtered shapesd"); FEEngine::filterElementalData(mesh, shapes_derivatives, *shapesd_filtered, *it, ghost_type, elem_filter); Array<Real> & stress_vect = this->stress(*it, ghost_type); Array<Real>::matrix_iterator sigma = stress_vect.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator B = shapesd_filtered->begin(spatial_dimension, nb_nodes_per_element); Array<Real>::matrix_iterator Bt_sigma_it = sigma_dphi_dx->begin(spatial_dimension, nb_nodes_per_element); for (UInt q = 0; q < nb_element * nb_quadrature_points; ++q, ++sigma, ++B, ++Bt_sigma_it) Bt_sigma_it->mul<false, false>(*sigma, *B); delete shapesd_filtered; /** * 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$ */ Array<Real> * int_sigma_dphi_dx = new Array<Real>( nb_element, nb_nodes_per_element * spatial_dimension, "int_sigma_x_dphi_/_dX"); fem->integrate(*sigma_dphi_dx, *int_sigma_dphi_dx, size_of_shapes_derivatives, *it, ghost_type, elem_filter); delete sigma_dphi_dx; /// assemble model->getDOFManager().assembleElementalArrayLocalArray(*int_sigma_dphi_dx, internal_force, *it, ghost_type, 1, elem_filter); delete int_sigma_dphi_dx; } } } else { switch (spatial_dimension) { case 1: this->assembleInternalForces<1>(ghost_type); break; case 2: this->assembleInternalForces<2>(ghost_type); break; case 3: this->assembleInternalForces<3>(ghost_type); break; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Compute the stress from the gradu * * @param[in] current_position nodes postition + displacements * @param[in] ghost_type compute the residual for _ghost or _not_ghost element */ void Material::computeAllStresses(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type)) { Array<UInt> & elem_filter = element_filter(type, ghost_type); if (elem_filter.getSize() == 0) continue; Array<Real> & gradu_vect = gradu(type, ghost_type); /// compute @f$\nabla u@f$ fem->gradientOnIntegrationPoints(model->getDisplacement(), gradu_vect, spatial_dimension, type, ghost_type, elem_filter); gradu_vect -= eigengradu(type, ghost_type); /// compute @f$\mathbf{\sigma}_q@f$ from @f$\nabla u@f$ computeStress(type, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::computeAllCauchyStresses(GhostType ghost_type) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(finite_deformation, "The Cauchy stress can only be " "computed if you are working in " "finite deformation."); for(auto type : element_filter.elementTypes(spatial_dimension, ghost_type)) { switch (spatial_dimension) { case 1: this->computeCauchyStress<1>(type, ghost_type); break; case 2: this->computeCauchyStress<2>(type, ghost_type); break; case 3: this->computeCauchyStress<3>(type, ghost_type); break; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void Material::computeCauchyStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real>::matrix_iterator gradu_it = this->gradu(el_type, ghost_type).begin(dim, dim); Array<Real>::matrix_iterator gradu_end = this->gradu(el_type, ghost_type).end(dim, dim); Array<Real>::matrix_iterator piola_it = this->piola_kirchhoff_2(el_type, ghost_type).begin(dim, dim); Array<Real>::matrix_iterator stress_it = this->stress(el_type, ghost_type).begin(dim, dim); Matrix<Real> F_tensor(dim, dim); for (; gradu_it != gradu_end; ++gradu_it, ++piola_it, ++stress_it) { Matrix<Real> & grad_u = *gradu_it; Matrix<Real> & piola = *piola_it; Matrix<Real> & sigma = *stress_it; gradUToF<dim>(grad_u, F_tensor); this->computeCauchyStressOnQuad<dim>(F_tensor, piola, sigma); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::setToSteadyState(GhostType ghost_type) { AKANTU_DEBUG_IN(); const Array<Real> & displacement = model->getDisplacement(); // resizeInternalArray(gradu); UInt spatial_dimension = model->getSpatialDimension(); for(auto type : element_filter.elementTypes(spatial_dimension, ghost_type)) { Array<UInt> & elem_filter = element_filter(type, ghost_type); Array<Real> & gradu_vect = gradu(type, ghost_type); /// compute @f$\nabla u@f$ fem->gradientOnIntegrationPoints(displacement, gradu_vect, spatial_dimension, type, ghost_type, elem_filter); setToSteadyState(type, ghost_type); } 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(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); for(auto type : element_filter.elementTypes(spatial_dimension, ghost_type)) { if (finite_deformation) { switch (spatial_dimension) { case 1: { assembleStiffnessMatrixNL<1>(type, ghost_type); assembleStiffnessMatrixL2<1>(type, ghost_type); break; } case 2: { assembleStiffnessMatrixNL<2>(type, ghost_type); assembleStiffnessMatrixL2<2>(type, ghost_type); break; } case 3: { assembleStiffnessMatrixNL<3>(type, ghost_type); assembleStiffnessMatrixL2<3>(type, ghost_type); break; } } } else { switch (spatial_dimension) { case 1: { assembleStiffnessMatrix<1>(type, ghost_type); break; } case 2: { assembleStiffnessMatrix<2>(type, ghost_type); break; } case 3: { assembleStiffnessMatrix<3>(type, ghost_type); break; } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void Material::assembleStiffnessMatrix(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<UInt> & elem_filter = element_filter(type, ghost_type); if (elem_filter.getSize()) { const Array<Real> & shapes_derivatives = fem->getShapesDerivatives(type, ghost_type); Array<Real> & gradu_vect = gradu(type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = fem->getNbIntegrationPoints(type, ghost_type); gradu_vect.resize(nb_quadrature_points * nb_element); fem->gradientOnIntegrationPoints(model->getDisplacement(), gradu_vect, dim, type, ghost_type, elem_filter); UInt tangent_size = getTangentStiffnessVoigtSize(dim); Array<Real> * tangent_stiffness_matrix = new Array<Real>( nb_element * nb_quadrature_points, tangent_size * tangent_size, "tangent_stiffness_matrix"); tangent_stiffness_matrix->clear(); computeTangentModuli(type, *tangent_stiffness_matrix, ghost_type); Array<Real> * shapesd_filtered = new Array<Real>(nb_element, dim * nb_nodes_per_element, "filtered shapesd"); FEEngine::filterElementalData(fem->getMesh(), shapes_derivatives, *shapesd_filtered, type, ghost_type, elem_filter); /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ UInt bt_d_b_size = dim * nb_nodes_per_element; Array<Real> * bt_d_b = new Array<Real>(nb_element * nb_quadrature_points, bt_d_b_size * bt_d_b_size, "B^t*D*B"); Matrix<Real> B(tangent_size, dim * nb_nodes_per_element); Matrix<Real> Bt_D(dim * nb_nodes_per_element, tangent_size); Array<Real>::matrix_iterator shapes_derivatives_filtered_it = shapesd_filtered->begin(dim, nb_nodes_per_element); Array<Real>::matrix_iterator Bt_D_B_it = bt_d_b->begin(dim * nb_nodes_per_element, dim * nb_nodes_per_element); Array<Real>::matrix_iterator D_it = tangent_stiffness_matrix->begin(tangent_size, tangent_size); Array<Real>::matrix_iterator D_end = tangent_stiffness_matrix->end(tangent_size, tangent_size); for (; D_it != D_end; ++D_it, ++Bt_D_B_it, ++shapes_derivatives_filtered_it) { Matrix<Real> & D = *D_it; Matrix<Real> & Bt_D_B = *Bt_D_B_it; VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix( *shapes_derivatives_filtered_it, B, nb_nodes_per_element); Bt_D.mul<true, false>(B, D); Bt_D_B.mul<false, false>(Bt_D, B); } delete tangent_stiffness_matrix; delete shapesd_filtered; /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Array<Real> * K_e = new Array<Real>(nb_element, bt_d_b_size * bt_d_b_size, "K_e"); fem->integrate(*bt_d_b, *K_e, bt_d_b_size * bt_d_b_size, type, ghost_type, elem_filter); delete bt_d_b; model->getDOFManager().assembleElementalMatricesToMatrix("K", "displacement", *K_e, type, ghost_type, _symmetric, elem_filter); delete K_e; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void Material::assembleStiffnessMatrixNL(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); const Array<Real> & shapes_derivatives = fem->getShapesDerivatives(type, ghost_type); Array<UInt> & elem_filter = element_filter(type, ghost_type); // Array<Real> & gradu_vect = delta_gradu(type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = fem->getNbIntegrationPoints(type, ghost_type); // gradu_vect.resize(nb_quadrature_points * nb_element); // fem->gradientOnIntegrationPoints(model->getIncrement(), gradu_vect, // dim, type, ghost_type, &elem_filter); Array<Real> * shapes_derivatives_filtered = new Array<Real>( nb_element * nb_quadrature_points, dim * nb_nodes_per_element, "shapes derivatives filtered"); Array<Real>::const_matrix_iterator shapes_derivatives_it = shapes_derivatives.begin(spatial_dimension, nb_nodes_per_element); Array<Real>::matrix_iterator shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension, nb_nodes_per_element); UInt * elem_filter_val = elem_filter.storage(); for (UInt e = 0; e < nb_element; ++e, ++elem_filter_val) for (UInt q = 0; q < nb_quadrature_points; ++q, ++shapes_derivatives_filtered_it) *shapes_derivatives_filtered_it = shapes_derivatives_it[*elem_filter_val * nb_quadrature_points + q]; /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ UInt bt_s_b_size = dim * nb_nodes_per_element; Array<Real> * bt_s_b = new Array<Real>(nb_element * nb_quadrature_points, bt_s_b_size * bt_s_b_size, "B^t*D*B"); UInt piola_matrix_size = getCauchyStressMatrixSize(dim); Matrix<Real> B(piola_matrix_size, bt_s_b_size); Matrix<Real> Bt_S(bt_s_b_size, piola_matrix_size); Matrix<Real> S(piola_matrix_size, piola_matrix_size); shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin( spatial_dimension, nb_nodes_per_element); Array<Real>::matrix_iterator Bt_S_B_it = bt_s_b->begin(bt_s_b_size, bt_s_b_size); Array<Real>::matrix_iterator Bt_S_B_end = bt_s_b->end(bt_s_b_size, bt_s_b_size); Array<Real>::matrix_iterator piola_it = piola_kirchhoff_2(type, ghost_type).begin(dim, dim); for (; Bt_S_B_it != Bt_S_B_end; ++Bt_S_B_it, ++shapes_derivatives_filtered_it, ++piola_it) { Matrix<Real> & Bt_S_B = *Bt_S_B_it; Matrix<Real> & Piola_kirchhoff_matrix = *piola_it; setCauchyStressMatrix<dim>(Piola_kirchhoff_matrix, S); VoigtHelper<dim>::transferBMatrixToBNL(*shapes_derivatives_filtered_it, B, nb_nodes_per_element); Bt_S.mul<true, false>(B, S); Bt_S_B.mul<false, false>(Bt_S, B); } delete shapes_derivatives_filtered; /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Array<Real> * K_e = new Array<Real > (nb_element, bt_s_b_size * bt_s_b_size, "K_e"); fem->integrate(*bt_s_b, *K_e, bt_s_b_size * bt_s_b_size, type, ghost_type, elem_filter); delete bt_s_b; model->getDOFManager().assembleElementalMatricesToMatrix("K", "displacement", *K_e, type, ghost_type, _symmetric, elem_filter); delete K_e; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void Material::assembleStiffnessMatrixL2(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); const Array<Real> & shapes_derivatives = fem->getShapesDerivatives(type, ghost_type); Array<UInt> & elem_filter = element_filter(type, ghost_type); Array<Real> & gradu_vect = gradu(type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = fem->getNbIntegrationPoints(type, ghost_type); gradu_vect.resize(nb_quadrature_points * nb_element); fem->gradientOnIntegrationPoints(model->getDisplacement(), gradu_vect, dim, type, ghost_type, elem_filter); UInt tangent_size = getTangentStiffnessVoigtSize(dim); Array<Real> * tangent_stiffness_matrix = new Array<Real>(nb_element * nb_quadrature_points, tangent_size * tangent_size, "tangent_stiffness_matrix"); tangent_stiffness_matrix->clear(); computeTangentModuli(type, *tangent_stiffness_matrix, ghost_type); Array<Real> * shapes_derivatives_filtered = new Array<Real>( nb_element * nb_quadrature_points, dim * nb_nodes_per_element, "shapes derivatives filtered"); Array<Real>::const_matrix_iterator shapes_derivatives_it = shapes_derivatives.begin(spatial_dimension, nb_nodes_per_element); Array<Real>::matrix_iterator shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension, nb_nodes_per_element); UInt * elem_filter_val = elem_filter.storage(); for (UInt e = 0; e < nb_element; ++e, ++elem_filter_val) for (UInt q = 0; q < nb_quadrature_points; ++q, ++shapes_derivatives_filtered_it) *shapes_derivatives_filtered_it = shapes_derivatives_it[*elem_filter_val * nb_quadrature_points + q]; /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ UInt bt_d_b_size = dim * nb_nodes_per_element; Array<Real> * bt_d_b = new Array<Real>(nb_element * nb_quadrature_points, bt_d_b_size * bt_d_b_size, "B^t*D*B"); Matrix<Real> B(tangent_size, dim * nb_nodes_per_element); Matrix<Real> B2(tangent_size, dim * nb_nodes_per_element); Matrix<Real> Bt_D(dim * nb_nodes_per_element, tangent_size); shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin( spatial_dimension, nb_nodes_per_element); Array<Real>::matrix_iterator Bt_D_B_it = bt_d_b->begin(dim * nb_nodes_per_element, dim * nb_nodes_per_element); Array<Real>::matrix_iterator grad_u_it = gradu_vect.begin(dim, dim); Array<Real>::matrix_iterator D_it = tangent_stiffness_matrix->begin(tangent_size, tangent_size); Array<Real>::matrix_iterator D_end = tangent_stiffness_matrix->end(tangent_size, tangent_size); for (; D_it != D_end; ++D_it, ++Bt_D_B_it, ++shapes_derivatives_filtered_it, ++grad_u_it) { Matrix<Real> & grad_u = *grad_u_it; Matrix<Real> & D = *D_it; Matrix<Real> & Bt_D_B = *Bt_D_B_it; // transferBMatrixToBL1<dim > (*shapes_derivatives_filtered_it, B, // nb_nodes_per_element); VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix( *shapes_derivatives_filtered_it, B, nb_nodes_per_element); VoigtHelper<dim>::transferBMatrixToBL2(*shapes_derivatives_filtered_it, grad_u, B2, nb_nodes_per_element); B += B2; Bt_D.mul<true, false>(B, D); Bt_D_B.mul<false, false>(Bt_D, B); } delete tangent_stiffness_matrix; delete shapes_derivatives_filtered; /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Array<Real> * K_e = new Array<Real>(nb_element, bt_d_b_size * bt_d_b_size, "K_e"); fem->integrate(*bt_d_b, *K_e, bt_d_b_size * bt_d_b_size, type, ghost_type, elem_filter); delete bt_d_b; model->getDOFManager().assembleElementalMatricesToMatrix("K", "displacement", *K_e, type, ghost_type, _symmetric, elem_filter); delete K_e; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void Material::assembleInternalForces(GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real> & internal_force = model->getInternalForce(); Mesh & mesh = fem->getMesh(); for(auto type : element_filter.elementTypes(spatial_dimension, ghost_type)) { const Array<Real> & shapes_derivatives = fem->getShapesDerivatives(type, ghost_type); Array<UInt> & elem_filter = element_filter(type, ghost_type); if (elem_filter.getSize() == 0) continue; UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent(); UInt nb_element = elem_filter.getSize(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = fem->getNbIntegrationPoints(type, ghost_type); Array<Real> * shapesd_filtered = new Array<Real>(nb_element, size_of_shapes_derivatives, "filtered shapesd"); FEEngine::filterElementalData(mesh, shapes_derivatives, *shapesd_filtered, type, ghost_type, elem_filter); Array<Real>::matrix_iterator shapes_derivatives_filtered_it = shapesd_filtered->begin(dim, nb_nodes_per_element); // Set stress vectors UInt stress_size = getTangentStiffnessVoigtSize(dim); // Set matrices B and BNL* UInt bt_s_size = dim * nb_nodes_per_element; Array<Real> * bt_s = new Array<Real>(nb_element * nb_quadrature_points, bt_s_size, "B^t*S"); Array<Real>::matrix_iterator grad_u_it = this->gradu(type, ghost_type).begin(dim, dim); Array<Real>::matrix_iterator grad_u_end = this->gradu(type, ghost_type).end(dim, dim); Array<Real>::matrix_iterator stress_it = this->piola_kirchhoff_2(type, ghost_type).begin(dim, dim); shapes_derivatives_filtered_it = shapesd_filtered->begin(dim, nb_nodes_per_element); Array<Real>::matrix_iterator bt_s_it = bt_s->begin(bt_s_size, 1); Matrix<Real> S_vect(stress_size, 1); Matrix<Real> B_tensor(stress_size, bt_s_size); Matrix<Real> B2_tensor(stress_size, bt_s_size); for (; grad_u_it != grad_u_end; ++grad_u_it, ++stress_it, ++shapes_derivatives_filtered_it, ++bt_s_it) { Matrix<Real> & grad_u = *grad_u_it; Matrix<Real> & r_it = *bt_s_it; Matrix<Real> & S_it = *stress_it; setCauchyStressArray<dim>(S_it, S_vect); VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix( *shapes_derivatives_filtered_it, B_tensor, nb_nodes_per_element); VoigtHelper<dim>::transferBMatrixToBL2(*shapes_derivatives_filtered_it, grad_u, B2_tensor, nb_nodes_per_element); B_tensor += B2_tensor; r_it.mul<true, false>(B_tensor, S_vect); } delete shapesd_filtered; /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Array<Real> * r_e = new Array<Real>(nb_element, bt_s_size, "r_e"); fem->integrate(*bt_s, *r_e, bt_s_size, type, ghost_type, elem_filter); delete bt_s; model->getDOFManager().assembleElementalArrayLocalArray(*r_e, internal_force, type, ghost_type, 1, elem_filter); delete r_e; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::computeAllStressesFromTangentModuli(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); for(auto type : element_filter.elementTypes(spatial_dimension, ghost_type)) { switch (spatial_dimension) { case 1: { computeAllStressesFromTangentModuli<1>(type, ghost_type); break; } case 2: { computeAllStressesFromTangentModuli<2>(type, ghost_type); break; } case 3: { computeAllStressesFromTangentModuli<3>(type, ghost_type); break; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void Material::computeAllStressesFromTangentModuli(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); const Array<Real> & shapes_derivatives = fem->getShapesDerivatives(type, ghost_type); Array<UInt> & elem_filter = element_filter(type, ghost_type); Array<Real> & gradu_vect = gradu(type, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element) { UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = fem->getNbIntegrationPoints(type, ghost_type); gradu_vect.resize(nb_quadrature_points * nb_element); Array<Real> & disp = model->getDisplacement(); fem->gradientOnIntegrationPoints(disp, gradu_vect, dim, type, ghost_type, elem_filter); UInt tangent_moduli_size = getTangentStiffnessVoigtSize(dim); Array<Real> * tangent_moduli_tensors = new Array<Real>( nb_element * nb_quadrature_points, tangent_moduli_size * tangent_moduli_size, "tangent_moduli_tensors"); tangent_moduli_tensors->clear(); computeTangentModuli(type, *tangent_moduli_tensors, ghost_type); Array<Real> * shapesd_filtered = new Array<Real>(nb_element, dim * nb_nodes_per_element, "filtered shapesd"); FEEngine::filterElementalData(fem->getMesh(), shapes_derivatives, *shapesd_filtered, type, ghost_type, elem_filter); Array<Real> filtered_u(nb_element, nb_nodes_per_element * spatial_dimension); FEEngine::extractNodalToElementField(fem->getMesh(), disp, filtered_u, type, ghost_type, elem_filter); /// compute @f$\mathbf{D} \mathbf{B} \mathbf{u}@f$ Array<Real>::matrix_iterator shapes_derivatives_filtered_it = shapesd_filtered->begin(dim, nb_nodes_per_element); Array<Real>::matrix_iterator D_it = tangent_moduli_tensors->begin(tangent_moduli_size, tangent_moduli_size); Array<Real>::matrix_iterator sigma_it = stress(type, ghost_type).begin(spatial_dimension, spatial_dimension); Array<Real>::vector_iterator u_it = filtered_u.begin(spatial_dimension * nb_nodes_per_element); Matrix<Real> B(tangent_moduli_size, spatial_dimension * nb_nodes_per_element); Vector<Real> Bu(tangent_moduli_size); Vector<Real> DBu(tangent_moduli_size); for (UInt e = 0; e < nb_element; ++e, ++u_it) { for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_it, ++shapes_derivatives_filtered_it, ++sigma_it) { Vector<Real> & u = *u_it; Matrix<Real> & sigma = *sigma_it; Matrix<Real> & D = *D_it; VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix( *shapes_derivatives_filtered_it, B, nb_nodes_per_element); Bu.mul<false>(B, u); DBu.mul<false>(D, Bu); // Voigt notation to full symmetric tensor for (UInt i = 0; i < dim; ++i) sigma(i, i) = DBu(i); if (dim == 2) { sigma(0, 1) = sigma(1, 0) = DBu(2); } else if (dim == 3) { sigma(1, 2) = sigma(2, 1) = DBu(3); sigma(0, 2) = sigma(2, 0) = DBu(4); sigma(0, 1) = sigma(1, 0) = DBu(5); } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::computePotentialEnergyByElements() { AKANTU_DEBUG_IN(); for(auto type : element_filter.elementTypes(spatial_dimension, _not_ghost)) { computePotentialEnergy(type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::computePotentialEnergy(ElementType, GhostType) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real Material::getPotentialEnergy() { AKANTU_DEBUG_IN(); Real epot = 0.; computePotentialEnergyByElements(); /// integrate the potential energy for each type of elements for(auto type : element_filter.elementTypes(spatial_dimension, _not_ghost)) { epot += fem->integrate(potential_energy(type, _not_ghost), type, _not_ghost, element_filter(type, _not_ghost)); } AKANTU_DEBUG_OUT(); return epot; } /* -------------------------------------------------------------------------- */ Real Material::getPotentialEnergy(ElementType & type, UInt index) { AKANTU_DEBUG_IN(); Real epot = 0.; Vector<Real> epot_on_quad_points(fem->getNbIntegrationPoints(type)); computePotentialEnergyByElement(type, index, epot_on_quad_points); epot = fem->integrate(epot_on_quad_points, type, element_filter(type)(index)); AKANTU_DEBUG_OUT(); return epot; } /* -------------------------------------------------------------------------- */ Real Material::getEnergy(std::string type) { AKANTU_DEBUG_IN(); if (type == "potential") return getPotentialEnergy(); AKANTU_DEBUG_OUT(); return 0.; } /* -------------------------------------------------------------------------- */ Real Material::getEnergy(std::string energy_id, ElementType type, UInt index) { AKANTU_DEBUG_IN(); if (energy_id == "potential") return getPotentialEnergy(type, index); AKANTU_DEBUG_OUT(); return 0.; } /* -------------------------------------------------------------------------- */ void Material::initElementalFieldInterpolation( const ElementTypeMapArray<Real> & interpolation_points_coordinates) { AKANTU_DEBUG_IN(); this->fem->initElementalFieldInterpolationFromIntegrationPoints( interpolation_points_coordinates, this->interpolation_points_matrices, this->interpolation_inverse_coordinates, &(this->element_filter)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::interpolateStress(ElementTypeMapArray<Real> & result, const GhostType ghost_type) { this->fem->interpolateElementalFieldFromIntegrationPoints( this->stress, this->interpolation_points_matrices, this->interpolation_inverse_coordinates, result, ghost_type, &(this->element_filter)); } /* -------------------------------------------------------------------------- */ void Material::interpolateStressOnFacets( ElementTypeMapArray<Real> & result, ElementTypeMapArray<Real> & by_elem_result, const GhostType ghost_type) { interpolateStress(by_elem_result, ghost_type); UInt stress_size = this->stress.getNbComponent(); const Mesh & mesh = this->model->getMesh(); const Mesh & mesh_facets = mesh.getMeshFacets(); for(auto type : element_filter.elementTypes(spatial_dimension, ghost_type)) { Array<UInt> & elem_fil = element_filter(type, ghost_type); Array<Real> & by_elem_res = by_elem_result(type, ghost_type); UInt nb_element = elem_fil.getSize(); UInt nb_element_full = this->model->getMesh().getNbElement(type, ghost_type); UInt nb_interpolation_points_per_elem = by_elem_res.getSize() / nb_element_full; const Array<Element> & facet_to_element = mesh_facets.getSubelementToElement(type, ghost_type); ElementType type_facet = Mesh::getFacetType(type); UInt nb_facet_per_elem = facet_to_element.getNbComponent(); UInt nb_quad_per_facet = nb_interpolation_points_per_elem / nb_facet_per_elem; Element element_for_comparison(type, 0, ghost_type); const Array<std::vector<Element> > * element_to_facet = NULL; GhostType current_ghost_type = _casper; Array<Real> * result_vec = NULL; Array<Real>::const_matrix_iterator result_it = by_elem_res.begin_reinterpret( stress_size, nb_interpolation_points_per_elem, nb_element_full); for (UInt el = 0; el < nb_element; ++el) { UInt global_el = elem_fil(el); element_for_comparison.element = global_el; for (UInt f = 0; f < nb_facet_per_elem; ++f) { Element facet_elem = facet_to_element(global_el, f); UInt global_facet = facet_elem.element; if (facet_elem.ghost_type != current_ghost_type) { current_ghost_type = facet_elem.ghost_type; element_to_facet = &mesh_facets.getElementToSubelement( type_facet, current_ghost_type); result_vec = &result(type_facet, current_ghost_type); } bool is_second_element = (*element_to_facet)(global_facet)[0] != element_for_comparison; for (UInt q = 0; q < nb_quad_per_facet; ++q) { Vector<Real> result_local(result_vec->storage() + (global_facet * nb_quad_per_facet + q) * result_vec->getNbComponent() + is_second_element * stress_size, stress_size); const Matrix<Real> & result_tmp(result_it[global_el]); result_local = result_tmp(f * nb_quad_per_facet + q); } } } } } /* -------------------------------------------------------------------------- */ template <typename T> const Array<T> & Material::getArray(__attribute__((unused)) const ID & vect_id, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); return NULL; } /* -------------------------------------------------------------------------- */ template <typename T> Array<T> & Material::getArray(__attribute__((unused)) const ID & vect_id, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); return NULL; } /* -------------------------------------------------------------------------- */ template <> const Array<Real> & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) const { std::stringstream sstr; std::string ghost_id = ""; if (ghost_type == _ghost) ghost_id = ":ghost"; sstr << getID() << ":" << vect_id << ":" << type << ghost_id; ID fvect_id = sstr.str(); try { return Memory::getArray<Real>(fvect_id); } catch (debug::Exception & e) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain a vector " << vect_id << "(" << fvect_id << ") [" << e << "]"); } } /* -------------------------------------------------------------------------- */ template <> Array<Real> & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) { std::stringstream sstr; std::string ghost_id = ""; if (ghost_type == _ghost) ghost_id = ":ghost"; sstr << getID() << ":" << vect_id << ":" << type << ghost_id; ID fvect_id = sstr.str(); try { return Memory::getArray<Real>(fvect_id); } catch (debug::Exception & e) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain a vector " << vect_id << "(" << fvect_id << ") [" << e << "]"); } } /* -------------------------------------------------------------------------- */ template <> const Array<UInt> & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) const { std::stringstream sstr; std::string ghost_id = ""; if (ghost_type == _ghost) ghost_id = ":ghost"; sstr << getID() << ":" << vect_id << ":" << type << ghost_id; ID fvect_id = sstr.str(); try { return Memory::getArray<UInt>(fvect_id); } catch (debug::Exception & e) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain a vector " << vect_id << "(" << fvect_id << ") [" << e << "]"); } } /* -------------------------------------------------------------------------- */ template <> Array<UInt> & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) { std::stringstream sstr; std::string ghost_id = ""; if (ghost_type == _ghost) ghost_id = ":ghost"; sstr << getID() << ":" << vect_id << ":" << type << ghost_id; ID fvect_id = sstr.str(); try { return Memory::getArray<UInt>(fvect_id); } catch (debug::Exception & e) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain a vector " << vect_id << "(" << fvect_id << ") [" << e << "]"); } } /* -------------------------------------------------------------------------- */ template <typename T> const InternalField<T> & Material::getInternal(__attribute__((unused)) const ID & int_id) const { AKANTU_DEBUG_TO_IMPLEMENT(); return NULL; } /* -------------------------------------------------------------------------- */ template <typename T> InternalField<T> & Material::getInternal(__attribute__((unused)) const ID & int_id) { AKANTU_DEBUG_TO_IMPLEMENT(); return NULL; } /* -------------------------------------------------------------------------- */ template <> const InternalField<Real> & Material::getInternal(const ID & int_id) const { std::map<ID, InternalField<Real> *>::const_iterator it = internal_vectors_real.find(getID() + ":" + int_id); if (it == internal_vectors_real.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain an internal " << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ template <> InternalField<Real> & Material::getInternal(const ID & int_id) { std::map<ID, InternalField<Real> *>::iterator it = internal_vectors_real.find(getID() + ":" + int_id); if (it == internal_vectors_real.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain an internal " << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ template <> const InternalField<UInt> & Material::getInternal(const ID & int_id) const { std::map<ID, InternalField<UInt> *>::const_iterator it = internal_vectors_uint.find(getID() + ":" + int_id); if (it == internal_vectors_uint.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain an internal " << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ template <> InternalField<UInt> & Material::getInternal(const ID & int_id) { std::map<ID, InternalField<UInt> *>::iterator it = internal_vectors_uint.find(getID() + ":" + int_id); if (it == internal_vectors_uint.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain an internal " << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ void Material::addElements(const Array<Element> & elements_to_add) { AKANTU_DEBUG_IN(); UInt mat_id = model->getInternalIndexFromID(getID()); Array<Element>::const_iterator<Element> el_begin = elements_to_add.begin(); Array<Element>::const_iterator<Element> el_end = elements_to_add.end(); for (; el_begin != el_end; ++el_begin) { const Element & element = *el_begin; Array<UInt> & mat_indexes = model->getMaterialByElement(element.type, element.ghost_type); Array<UInt> & mat_loc_num = model->getMaterialLocalNumbering(element.type, element.ghost_type); UInt index = this->addElement(element.type, element.element, element.ghost_type); mat_indexes(element.element) = mat_id; mat_loc_num(element.element) = index; } this->resizeInternals(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::removeElements(const Array<Element> & elements_to_remove) { AKANTU_DEBUG_IN(); Array<Element>::const_iterator<Element> el_begin = elements_to_remove.begin(); Array<Element>::const_iterator<Element> el_end = elements_to_remove.end(); if (el_begin == el_end) return; ElementTypeMapArray<UInt> material_local_new_numbering("remove mat filter elem", getID(), getMemoryID()); Element element; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; element.ghost_type = ghost_type; ElementTypeMapArray<UInt>::type_iterator it = element_filter.firstType(_all_dimensions, ghost_type, _ek_not_defined); ElementTypeMapArray<UInt>::type_iterator end = element_filter.lastType(_all_dimensions, ghost_type, _ek_not_defined); for (; it != end; ++it) { ElementType type = *it; element.type = type; Array<UInt> & elem_filter = this->element_filter(type, ghost_type); Array<UInt> & mat_loc_num = this->model->getMaterialLocalNumbering(type, ghost_type); if (!material_local_new_numbering.exists(type, ghost_type)) material_local_new_numbering.alloc(elem_filter.getSize(), 1, type, ghost_type); Array<UInt> & mat_renumbering = material_local_new_numbering(type, ghost_type); UInt nb_element = elem_filter.getSize(); element.kind = (*el_begin).kind; Array<UInt> elem_filter_tmp; UInt new_id = 0; for (UInt el = 0; el < nb_element; ++el) { element.element = elem_filter(el); if (std::find(el_begin, el_end, element) == el_end) { elem_filter_tmp.push_back(element.element); mat_renumbering(el) = new_id; mat_loc_num(element.element) = new_id; ++new_id; } else { mat_renumbering(el) = UInt(-1); } } elem_filter.resize(elem_filter_tmp.getSize()); elem_filter.copy(elem_filter_tmp); } } for (std::map<ID, InternalField<Real> *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->removeIntegrationPoints(material_local_new_numbering); for (std::map<ID, InternalField<UInt> *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->removeIntegrationPoints(material_local_new_numbering); for (std::map<ID, InternalField<bool> *>::iterator it = internal_vectors_bool.begin(); it != internal_vectors_bool.end(); ++it) it->second->removeIntegrationPoints(material_local_new_numbering); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::resizeInternals() { AKANTU_DEBUG_IN(); for (std::map<ID, InternalField<Real> *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->resize(); for (std::map<ID, InternalField<UInt> *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->resize(); for (std::map<ID, InternalField<bool> *>::iterator it = internal_vectors_bool.begin(); it != internal_vectors_bool.end(); ++it) it->second->resize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::onElementsAdded(const Array<Element> &, const NewElementsEvent &) { this->resizeInternals(); } /* -------------------------------------------------------------------------- */ void Material::onElementsRemoved( const Array<Element> & element_list, const ElementTypeMapArray<UInt> & new_numbering, __attribute__((unused)) const RemovedElementsEvent & event) { UInt my_num = model->getInternalIndexFromID(getID()); ElementTypeMapArray<UInt> material_local_new_numbering("remove mat filter elem", getID(), getMemoryID()); Array<Element>::const_iterator<Element> el_begin = element_list.begin(); Array<Element>::const_iterator<Element> el_end = element_list.end(); for (ghost_type_t::iterator g = ghost_type_t::begin(); g != ghost_type_t::end(); ++g) { GhostType gt = *g; ElementTypeMapArray<UInt>::type_iterator it = new_numbering.firstType(_all_dimensions, gt, _ek_not_defined); ElementTypeMapArray<UInt>::type_iterator end = new_numbering.lastType(_all_dimensions, gt, _ek_not_defined); for (; it != end; ++it) { ElementType type = *it; if (element_filter.exists(type, gt) && element_filter(type, gt).getSize()) { Array<UInt> & elem_filter = element_filter(type, gt); Array<UInt> & mat_indexes = this->model->getMaterialByElement(*it, gt); Array<UInt> & mat_loc_num = this->model->getMaterialLocalNumbering(*it, gt); UInt nb_element = this->model->getMesh().getNbElement(type, gt); // all materials will resize of the same size... mat_indexes.resize(nb_element); mat_loc_num.resize(nb_element); if (!material_local_new_numbering.exists(type, gt)) material_local_new_numbering.alloc(elem_filter.getSize(), 1, type, gt); Array<UInt> & mat_renumbering = material_local_new_numbering(type, gt); const Array<UInt> & renumbering = new_numbering(type, gt); Array<UInt> elem_filter_tmp; UInt ni = 0; Element el; el.type = type; el.ghost_type = gt; el.kind = Mesh::getKind(type); for (UInt i = 0; i < elem_filter.getSize(); ++i) { el.element = elem_filter(i); if (std::find(el_begin, el_end, el) == el_end) { UInt new_el = renumbering(el.element); AKANTU_DEBUG_ASSERT( new_el != UInt(-1), "A not removed element as been badly renumbered"); elem_filter_tmp.push_back(new_el); mat_renumbering(i) = ni; mat_indexes(new_el) = my_num; mat_loc_num(new_el) = ni; ++ni; } else { mat_renumbering(i) = UInt(-1); } } elem_filter.resize(elem_filter_tmp.getSize()); elem_filter.copy(elem_filter_tmp); } } } for (std::map<ID, InternalField<Real> *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->removeIntegrationPoints(material_local_new_numbering); for (std::map<ID, InternalField<UInt> *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->removeIntegrationPoints(material_local_new_numbering); for (std::map<ID, InternalField<bool> *>::iterator it = internal_vectors_bool.begin(); it != internal_vectors_bool.end(); ++it) it->second->removeIntegrationPoints(material_local_new_numbering); } /* -------------------------------------------------------------------------- */ void Material::onBeginningSolveStep(__attribute__((unused)) const AnalysisMethod & method) { this->savePreviousState(); } /* -------------------------------------------------------------------------- */ void Material::onEndSolveStep(__attribute__((unused)) const AnalysisMethod & method) { ElementTypeMapArray<UInt>::type_iterator it = this->element_filter.firstType( _all_dimensions, _not_ghost, _ek_not_defined); ElementTypeMapArray<UInt>::type_iterator end = element_filter.lastType(_all_dimensions, _not_ghost, _ek_not_defined); for (; it != end; ++it) { this->updateEnergies(*it, _not_ghost); } } /* -------------------------------------------------------------------------- */ void Material::onDamageIteration() { this->savePreviousState(); } /* -------------------------------------------------------------------------- */ void Material::onDamageUpdate() { ElementTypeMapArray<UInt>::type_iterator it = this->element_filter.firstType( _all_dimensions, _not_ghost, _ek_not_defined); ElementTypeMapArray<UInt>::type_iterator end = element_filter.lastType(_all_dimensions, _not_ghost, _ek_not_defined); for (; it != end; ++it) { this->updateEnergiesAfterDamage(*it, _not_ghost); } } /* -------------------------------------------------------------------------- */ void Material::onDump() { if (this->isFiniteDeformation()) this->computeAllCauchyStresses(_not_ghost); } /* -------------------------------------------------------------------------- */ void Material::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; std::string type = getID().substr(getID().find_last_of(":") + 1); stream << space << "Material " << type << " [" << std::endl; Parsable::printself(stream, indent); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ /// extrapolate internal values void Material::extrapolateInternal(const ID & id, const Element & element, __attribute__((unused)) const Matrix<Real> & point, Matrix<Real> & extrapolated) { if (this->isInternal<Real>(id, element.kind)) { UInt nb_element = this->element_filter(element.type, element.ghost_type).getSize(); const ID name = this->getID() + ":" + id; UInt nb_quads = this->internal_vectors_real[name]->getFEEngine().getNbIntegrationPoints( element.type, element.ghost_type); const Array<Real> & internal = this->getArray<Real>(id, element.type, element.ghost_type); UInt nb_component = internal.getNbComponent(); Array<Real>::const_matrix_iterator internal_it = internal.begin_reinterpret(nb_component, nb_quads, nb_element); Element local_element = this->convertToLocalElement(element); /// instead of really extrapolating, here the value of the first GP /// is copied into the result vector. This works only for linear /// elements /// @todo extrapolate!!!! AKANTU_DEBUG_WARNING("This is a fix, values are not truly extrapolated"); const Matrix<Real> & values = internal_it[local_element.element]; UInt index = 0; Vector<Real> tmp(nb_component); for (UInt j = 0; j < values.cols(); ++j) { tmp = values(j); if (tmp.norm() > 0) { index = j; break; } } for (UInt i = 0; i < extrapolated.size(); ++i) { extrapolated(i) = values(index); } } else { Matrix<Real> default_values(extrapolated.rows(), extrapolated.cols(), 0.); extrapolated = default_values; } } /* -------------------------------------------------------------------------- */ void Material::applyEigenGradU(const Matrix<Real> & prescribed_eigen_grad_u, const GhostType ghost_type) { ElementTypeMapArray<UInt>::type_iterator it = this->element_filter.firstType( _all_dimensions, _not_ghost, _ek_not_defined); ElementTypeMapArray<UInt>::type_iterator end = element_filter.lastType(_all_dimensions, _not_ghost, _ek_not_defined); for (; it != end; ++it) { ElementType type = *it; if (!element_filter(type, ghost_type).getSize()) continue; Array<Real>::matrix_iterator eigen_it = this->eigengradu(type, ghost_type) .begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator eigen_end = this->eigengradu(type, ghost_type) .end(spatial_dimension, spatial_dimension); for (; eigen_it != eigen_end; ++eigen_it) { Matrix<Real> & current_eigengradu = *eigen_it; current_eigengradu = prescribed_eigen_grad_u; } } } -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/material.hh b/src/model/solid_mechanics/material.hh index dd3307b59..5d5fea53d 100644 --- a/src/model/solid_mechanics/material.hh +++ b/src/model/solid_mechanics/material.hh @@ -1,664 +1,664 @@ /** * @file material.hh * * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Wed Nov 25 2015 * * @brief Mother class for all materials * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "aka_voigthelper.hh" #include "parser.hh" #include "parsable.hh" #include "data_accessor.hh" #include "integration_point.hh" /* -------------------------------------------------------------------------- */ #include "internal_field.hh" #include "random_internal_field.hh" /* -------------------------------------------------------------------------- */ #include "mesh_events.hh" #include "solid_mechanics_model_event_handler.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_HH__ #define __AKANTU_MATERIAL_HH__ /* -------------------------------------------------------------------------- */ namespace akantu { class Model; class SolidMechanicsModel; } -__BEGIN_AKANTU__ +namespace akantu { /** * Interface of all materials * Prerequisites for a new material * - inherit from this class * - implement the following methods: * \code * virtual Real getStableTimeStep(Real h, const Element & element = * ElementNull); * * virtual void computeStress(ElementType el_type, * GhostType ghost_type = _not_ghost); * * virtual void computeTangentStiffness(const ElementType & el_type, * Array<Real> & tangent_matrix, * GhostType ghost_type = _not_ghost); * \endcode * */ class Material : public Memory, public DataAccessor<Element>, public Parsable, public MeshEventHandler, protected SolidMechanicsModelEventHandler { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: #if __cplusplus > 199711L Material(const Material & mat) = delete; Material & operator=(const Material & mat) = delete; #endif /// Initialize material with defaults Material(SolidMechanicsModel & model, const ID & id = ""); /// Initialize material with custom mesh & fe_engine Material(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id = ""); /// Destructor virtual ~Material(); protected: void initialize(); /* ------------------------------------------------------------------------ */ /* Function that materials can/should reimplement */ /* ------------------------------------------------------------------------ */ protected: /// constitutive law virtual void computeStress(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the tangent stiffness matrix virtual void computeTangentModuli(__attribute__((unused)) const ElementType & el_type, __attribute__((unused)) Array<Real> & tangent_matrix, __attribute__((unused)) GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the potential energy virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the potential energy for an element virtual void computePotentialEnergyByElement(__attribute__((unused)) ElementType type, __attribute__((unused)) UInt index, __attribute__((unused)) Vector<Real> & epot_on_quad_points) { AKANTU_DEBUG_TO_IMPLEMENT(); } virtual void updateEnergies(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) {} virtual void updateEnergiesAfterDamage(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) {} /// set the material to steady state (to be implemented for materials that /// need it) virtual void setToSteadyState(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) {} /// function called to update the internal parameters when the modifiable /// parameters are modified virtual void updateInternalParameters() {} public: /// extrapolate internal values virtual void extrapolateInternal(const ID & id, const Element & element, const Matrix<Real> & points, Matrix<Real> & extrapolated); /// compute the p-wave speed in the material virtual Real getPushWaveSpeed(__attribute__((unused)) const Element & element) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the s-wave speed in the material virtual Real getShearWaveSpeed(__attribute__((unused)) const Element & element) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// get a material celerity to compute the stable time step (default: is the /// push wave speed) virtual Real getCelerity(const Element & element) const { return getPushWaveSpeed(element); } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: template <typename T> void registerInternal(__attribute__((unused)) InternalField<T> & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); } template <typename T> void unregisterInternal(__attribute__((unused)) InternalField<T> & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// initialize the material computed parameter virtual void initMaterial(); /// compute the residual for this material // virtual void updateResidual(GhostType ghost_type = _not_ghost); /// assemble the residual for this material virtual void assembleInternalForces(GhostType ghost_type); /// save the stress in the previous_stress if needed virtual void savePreviousState(); /// compute the stresses for this material virtual void computeAllStresses(GhostType ghost_type = _not_ghost); virtual void computeAllStressesFromTangentModuli(GhostType ghost_type = _not_ghost); virtual void computeAllCauchyStresses(GhostType ghost_type = _not_ghost); /// set material to steady state void setToSteadyState(GhostType ghost_type = _not_ghost); /// compute the stiffness matrix virtual void assembleStiffnessMatrix(GhostType ghost_type); /// add an element to the local mesh filter inline UInt addElement(const ElementType & type, UInt element, const GhostType & ghost_type); /// add many elements at once void addElements(const Array<Element> & elements_to_add); /// remove many element at once void removeElements(const Array<Element> & elements_to_remove); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /** * interpolate stress on given positions for each element by means * of a geometrical interpolation on quadrature points */ void interpolateStress(ElementTypeMapArray<Real> & result, const GhostType ghost_type = _not_ghost); /** * interpolate stress on given positions for each element by means * of a geometrical interpolation on quadrature points and store the * results per facet */ void interpolateStressOnFacets(ElementTypeMapArray<Real> & result, ElementTypeMapArray<Real> & by_elem_result, const GhostType ghost_type = _not_ghost); /** * function to initialize the elemental field interpolation * function by inverting the quadrature points' coordinates */ void initElementalFieldInterpolation( const ElementTypeMapArray<Real> & interpolation_points_coordinates); /* ------------------------------------------------------------------------ */ /* Common part */ /* ------------------------------------------------------------------------ */ protected: /* ------------------------------------------------------------------------ */ inline UInt getTangentStiffnessVoigtSize(UInt spatial_dimension) const; /// compute the potential energy by element void computePotentialEnergyByElements(); /// resize the intenals arrays virtual void resizeInternals(); /* ------------------------------------------------------------------------ */ /* Finite deformation functions */ /* This functions area implementing what is described in the paper of Bathe */ /* et al, in IJNME, Finite Element Formulations For Large Deformation */ /* Dynamic Analysis, Vol 9, 353-386, 1975 */ /* ------------------------------------------------------------------------ */ protected: /// assemble the residual template <UInt dim> void assembleInternalForces(GhostType ghost_type); /// Computation of Cauchy stress tensor in the case of finite deformation from /// the 2nd Piola-Kirchhoff for a given element type template <UInt dim> void computeCauchyStress(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost); /// Computation the Cauchy stress the 2nd Piola-Kirchhoff and the deformation /// gradient template <UInt dim> inline void computeCauchyStressOnQuad(const Matrix<Real> & F, const Matrix<Real> & S, Matrix<Real> & cauchy, const Real & C33 = 1.0) const; template <UInt dim> void computeAllStressesFromTangentModuli(const ElementType & type, GhostType ghost_type); template <UInt dim> void assembleStiffnessMatrix(const ElementType & type, GhostType ghost_type); /// assembling in finite deformation template <UInt dim> void assembleStiffnessMatrixNL(const ElementType & type, GhostType ghost_type); template <UInt dim> void assembleStiffnessMatrixL2(const ElementType & type, GhostType ghost_type); /// Size of the Stress matrix for the case of finite deformation see: Bathe et /// al, IJNME, Vol 9, 353-386, 1975 inline UInt getCauchyStressMatrixSize(UInt spatial_dimension) const; /// Sets the stress matrix according to Bathe et al, IJNME, Vol 9, 353-386, /// 1975 template <UInt dim> inline void setCauchyStressMatrix(const Matrix<Real> & S_t, Matrix<Real> & sigma); /// write the stress tensor in the Voigt notation. template <UInt dim> inline void setCauchyStressArray(const Matrix<Real> & S_t, Matrix<Real> & sigma_voight); /* ------------------------------------------------------------------------ */ /* Conversion functions */ /* ------------------------------------------------------------------------ */ public: template <UInt dim> static inline void gradUToF(const Matrix<Real> & grad_u, Matrix<Real> & F); static inline void rightCauchy(const Matrix<Real> & F, Matrix<Real> & C); static inline void leftCauchy(const Matrix<Real> & F, Matrix<Real> & B); template <UInt dim> static inline void gradUToEpsilon(const Matrix<Real> & grad_u, Matrix<Real> & epsilon); template <UInt dim> static inline void gradUToGreenStrain(const Matrix<Real> & grad_u, Matrix<Real> & epsilon); static inline Real stressToVonMises(const Matrix<Real> & stress); protected: /// converts global element to local element inline Element convertToLocalElement(const Element & global_element) const; /// converts local element to global element inline Element convertToGlobalElement(const Element & local_element) const; /// converts global quadrature point to local quadrature point inline IntegrationPoint convertToLocalPoint(const IntegrationPoint & global_point) const; /// converts local quadrature point to global quadrature point inline IntegrationPoint convertToGlobalPoint(const IntegrationPoint & local_point) const; /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ public: virtual inline UInt getNbData(const Array<Element> & elements, const SynchronizationTag & tag) const; virtual inline void packData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) const; virtual inline void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag); template <typename T> inline void packElementDataHelper(const ElementTypeMapArray<T> & data_to_pack, CommunicationBuffer & buffer, const Array<Element> & elements, const ID & fem_id = ID()) const; template <typename T> inline void unpackElementDataHelper(ElementTypeMapArray<T> & data_to_unpack, CommunicationBuffer & buffer, const Array<Element> & elements, const ID & fem_id = ID()); /* ------------------------------------------------------------------------ */ /* MeshEventHandler inherited members */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ virtual void onNodesAdded(__attribute__((unused)) const Array<UInt> & nodes_list, __attribute__((unused)) const NewNodesEvent & event){}; virtual void onNodesRemoved(__attribute__((unused)) const Array<UInt> & nodes_list, __attribute__((unused)) const Array<UInt> & new_numbering, __attribute__((unused)) const RemovedNodesEvent & event){}; virtual void onElementsAdded(const Array<Element> & element_list, const NewElementsEvent & event); virtual void onElementsRemoved(const Array<Element> & element_list, const ElementTypeMapArray<UInt> & new_numbering, const RemovedElementsEvent & event); virtual void onElementsChanged( __attribute__((unused)) const Array<Element> & old_elements_list, __attribute__((unused)) const Array<Element> & new_elements_list, __attribute__((unused)) const ElementTypeMapArray<UInt> & new_numbering, __attribute__((unused)) const ChangedElementsEvent & event){}; /* ------------------------------------------------------------------------ */ /* SolidMechanicsModelEventHandler inherited members */ /* ------------------------------------------------------------------------ */ public: virtual void onBeginningSolveStep(const AnalysisMethod & method); virtual void onEndSolveStep(const AnalysisMethod & method); virtual void onDamageIteration(); virtual void onDamageUpdate(); virtual void onDump(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(Name, name, const std::string &); AKANTU_GET_MACRO(Model, *model, const SolidMechanicsModel &) AKANTU_GET_MACRO(ID, Memory::getID(), const ID &); AKANTU_GET_MACRO(Rho, rho, Real); AKANTU_SET_MACRO(Rho, rho, Real); AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt); /// return the potential energy for the subset of elements contained by the /// material Real getPotentialEnergy(); /// return the potential energy for the provided element Real getPotentialEnergy(ElementType & type, UInt index); /// return the energy (identified by id) for the subset of elements contained /// by the material virtual Real getEnergy(std::string energy_id); /// return the energy (identified by id) for the provided element virtual Real getEnergy(std::string energy_id, ElementType type, UInt index); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(GradU, gradu, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Stress, stress, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PotentialEnergy, potential_energy, Real); AKANTU_GET_MACRO(GradU, gradu, const ElementTypeMapArray<Real> &); AKANTU_GET_MACRO(Stress, stress, const ElementTypeMapArray<Real> &); AKANTU_GET_MACRO(ElementFilter, element_filter, const ElementTypeMapArray<UInt> &); AKANTU_GET_MACRO(FEEngine, *fem, FEEngine &); bool isNonLocal() const { return is_non_local; } template <typename T> const Array<T> & getArray(const ID & id, const ElementType & type, const GhostType & ghost_type = _not_ghost) const; template <typename T> Array<T> & getArray(const ID & id, const ElementType & type, const GhostType & ghost_type = _not_ghost); template <typename T> const InternalField<T> & getInternal(const ID & id) const; template <typename T> InternalField<T> & getInternal(const ID & id); template <typename T> inline bool isInternal(const ID & id, const ElementKind & element_kind) const; template <typename T> ElementTypeMap<UInt> getInternalDataPerElem(const ID & id, const ElementKind & element_kind) const; bool isFiniteDeformation() const { return finite_deformation; } bool isInelasticDeformation() const { return inelastic_deformation; } template <typename T> inline void setParam(const ID & param, T value); inline const Parameter & getParam(const ID & param) const; template <typename T> void flattenInternal(const std::string & field_id, ElementTypeMapArray<T> & internal_flat, const GhostType ghost_type = _not_ghost, ElementKind element_kind = _ek_not_defined) const; /// apply a constant eigengrad_u everywhere in the material virtual void applyEigenGradU(const Matrix<Real> & prescribed_eigen_grad_u, const GhostType = _not_ghost); /// specify if the matrix need to be recomputed for this material virtual bool hasStiffnessMatrixChanged() { return true; } protected: bool isInit() const { return is_init; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// boolean to know if the material has been initialized bool is_init; std::map<ID, InternalField<Real> *> internal_vectors_real; std::map<ID, InternalField<UInt> *> internal_vectors_uint; std::map<ID, InternalField<bool> *> internal_vectors_bool; protected: /// Link to the fem object in the model FEEngine * fem; /// Finite deformation bool finite_deformation; /// Finite deformation bool inelastic_deformation; /// material name std::string name; /// The model to witch the material belong SolidMechanicsModel * model; /// density : rho Real rho; /// spatial dimension UInt spatial_dimension; /// list of element handled by the material ElementTypeMapArray<UInt> element_filter; /// stresses arrays ordered by element types InternalField<Real> stress; /// eigengrad_u arrays ordered by element types InternalField<Real> eigengradu; /// grad_u arrays ordered by element types InternalField<Real> gradu; /// Green Lagrange strain (Finite deformation) InternalField<Real> green_strain; /// Second Piola-Kirchhoff stress tensor arrays ordered by element types /// (Finite deformation) InternalField<Real> piola_kirchhoff_2; /// potential energy by element InternalField<Real> potential_energy; /// tell if using in non local mode or not bool is_non_local; /// tell if the material need the previous stress state bool use_previous_stress; /// tell if the material need the previous strain state bool use_previous_gradu; /// elemental field interpolation coordinates InternalField<Real> interpolation_inverse_coordinates; /// elemental field interpolation points InternalField<Real> interpolation_points_matrices; /// vector that contains the names of all the internals that need to /// be transferred when material interfaces move std::vector<ID> internals_to_transfer; }; /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const Material & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #include "material_inline_impl.cc" #include "internal_field_tmpl.hh" #include "random_internal_field_tmpl.hh" /* -------------------------------------------------------------------------- */ /* Auto loop */ /* -------------------------------------------------------------------------- */ /// This can be used to automatically write the loop on quadrature points in /// functions such as computeStress. This macro in addition to write the loop /// provides two tensors (matrices) sigma and grad_u #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type) \ Array<Real>::matrix_iterator gradu_it = \ this->gradu(el_type, ghost_type) \ .begin(this->spatial_dimension, this->spatial_dimension); \ Array<Real>::matrix_iterator gradu_end = \ this->gradu(el_type, ghost_type) \ .end(this->spatial_dimension, this->spatial_dimension); \ \ this->stress(el_type, ghost_type) \ .resize(this->gradu(el_type, ghost_type).getSize()); \ \ Array<Real>::iterator<Matrix<Real> > stress_it = \ this->stress(el_type, ghost_type) \ .begin(this->spatial_dimension, this->spatial_dimension); \ \ if (this->isFiniteDeformation()) { \ this->piola_kirchhoff_2(el_type, ghost_type) \ .resize(this->gradu(el_type, ghost_type).getSize()); \ stress_it = this->piola_kirchhoff_2(el_type, ghost_type) \ .begin(this->spatial_dimension, this->spatial_dimension); \ } \ \ for (; gradu_it != gradu_end; ++gradu_it, ++stress_it) { \ Matrix<Real> & __attribute__((unused)) grad_u = *gradu_it; \ Matrix<Real> & __attribute__((unused)) sigma = *stress_it #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END } /// This can be used to automatically write the loop on quadrature points in /// functions such as computeTangentModuli. This macro in addition to write the /// loop provides two tensors (matrices) sigma_tensor, grad_u, and a matrix /// where the elemental tangent moduli should be stored in Voigt Notation #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_mat) \ Array<Real>::matrix_iterator gradu_it = \ this->gradu(el_type, ghost_type) \ .begin(this->spatial_dimension, this->spatial_dimension); \ Array<Real>::matrix_iterator gradu_end = \ this->gradu(el_type, ghost_type) \ .end(this->spatial_dimension, this->spatial_dimension); \ Array<Real>::matrix_iterator sigma_it = \ this->stress(el_type, ghost_type) \ .begin(this->spatial_dimension, this->spatial_dimension); \ \ tangent_mat.resize(this->gradu(el_type, ghost_type).getSize()); \ \ UInt tangent_size = \ this->getTangentStiffnessVoigtSize(this->spatial_dimension); \ Array<Real>::matrix_iterator tangent_it = \ tangent_mat.begin(tangent_size, tangent_size); \ \ for (; gradu_it != gradu_end; ++gradu_it, ++sigma_it, ++tangent_it) { \ Matrix<Real> & __attribute__((unused)) grad_u = *gradu_it; \ Matrix<Real> & __attribute__((unused)) sigma_tensor = *sigma_it; \ Matrix<Real> & tangent = *tangent_it #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END } /* -------------------------------------------------------------------------- */ #define INSTANTIATE_MATERIAL(mat_name) \ template class mat_name<1>; \ template class mat_name<2>; \ template class mat_name<3> #endif /* __AKANTU_MATERIAL_HH__ */ // LocalWords: ElementNull diff --git a/src/model/solid_mechanics/material_inline_impl.cc b/src/model/solid_mechanics/material_inline_impl.cc index d09480d68..fbd6f1946 100644 --- a/src/model/solid_mechanics/material_inline_impl.cc +++ b/src/model/solid_mechanics/material_inline_impl.cc @@ -1,461 +1,461 @@ /** * @file material_inline_impl.cc * * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue Jul 27 2010 * @date last modification: Wed Nov 25 2015 * * @brief Implementation of the inline functions of the class material * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_INLINE_IMPL_CC__ #define __AKANTU_MATERIAL_INLINE_IMPL_CC__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ inline UInt Material::addElement(const ElementType & type, UInt element, const GhostType & ghost_type) { Array<UInt> & el_filter = this->element_filter(type, ghost_type); el_filter.push_back(element); return el_filter.getSize() - 1; } /* -------------------------------------------------------------------------- */ inline UInt Material::getTangentStiffnessVoigtSize(UInt dim) const { return (dim * (dim - 1) / 2 + dim); } /* -------------------------------------------------------------------------- */ inline UInt Material::getCauchyStressMatrixSize(UInt dim) const { return (dim * dim); } /* -------------------------------------------------------------------------- */ template <UInt dim> inline void Material::gradUToF(const Matrix<Real> & grad_u, Matrix<Real> & F) { AKANTU_DEBUG_ASSERT(F.size() >= grad_u.size() && grad_u.size() == dim * dim, "The dimension of the tensor F should be greater or " "equal to the dimension of the tensor grad_u."); F.eye(); for (UInt i = 0; i < dim; ++i) for (UInt j = 0; j < dim; ++j) F(i, j) += grad_u(i, j); } /* -------------------------------------------------------------------------- */ template <UInt dim> inline void Material::computeCauchyStressOnQuad(const Matrix<Real> & F, const Matrix<Real> & piola, Matrix<Real> & sigma, const Real & C33) const { Real J = F.det() * sqrt(C33); Matrix<Real> F_S(dim, dim); F_S.mul<false, false>(F, piola); Real constant = J ? 1. / J : 0; sigma.mul<false, true>(F_S, F, constant); } /* -------------------------------------------------------------------------- */ inline void Material::rightCauchy(const Matrix<Real> & F, Matrix<Real> & C) { C.mul<true, false>(F, F); } /* -------------------------------------------------------------------------- */ inline void Material::leftCauchy(const Matrix<Real> & F, Matrix<Real> & B) { B.mul<false, true>(F, F); } /* -------------------------------------------------------------------------- */ template <UInt dim> inline void Material::gradUToEpsilon(const Matrix<Real> & grad_u, Matrix<Real> & epsilon) { for (UInt i = 0; i < dim; ++i) for (UInt j = 0; j < dim; ++j) epsilon(i, j) = 0.5 * (grad_u(i, j) + grad_u(j, i)); } /* -------------------------------------------------------------------------- */ template <UInt dim> inline void Material::gradUToGreenStrain(const Matrix<Real> & grad_u, Matrix<Real> & epsilon) { epsilon.mul<true, false>(grad_u, grad_u, .5); for (UInt i = 0; i < dim; ++i) for (UInt j = 0; j < dim; ++j) epsilon(i, j) += 0.5 * (grad_u(i, j) + grad_u(j, i)); } /* -------------------------------------------------------------------------- */ inline Real Material::stressToVonMises(const Matrix<Real> & stress) { // compute deviatoric stress UInt dim = stress.cols(); Matrix<Real> deviatoric_stress = Matrix<Real>::eye(dim, -1. * stress.trace() / 3.); for (UInt i = 0; i < dim; ++i) for (UInt j = 0; j < dim; ++j) deviatoric_stress(i, j) += stress(i, j); // return Von Mises stress return std::sqrt(3. * deviatoric_stress.doubleDot(deviatoric_stress) / 2.); } /* ---------------------------------------------------------------------------*/ template <UInt dim> inline void Material::setCauchyStressArray(const Matrix<Real> & S_t, Matrix<Real> & sigma_voight) { AKANTU_DEBUG_IN(); sigma_voight.clear(); // see Finite ekement formulations for large deformation dynamic analysis, // Bathe et al. IJNME vol 9, 1975, page 364 ^t\tau /* * 1d: [ s11 ]' * 2d: [ s11 s22 s12 ]' * 3d: [ s11 s22 s33 s23 s13 s12 ] */ for (UInt i = 0; i < dim; ++i) // diagonal terms sigma_voight(i, 0) = S_t(i, i); for (UInt i = 1; i < dim; ++i) // term s12 in 2D and terms s23 s13 in 3D sigma_voight(dim + i - 1, 0) = S_t(dim - i - 1, dim - 1); for (UInt i = 2; i < dim; ++i) // term s13 in 3D sigma_voight(dim + i, 0) = S_t(0, 1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> inline void Material::setCauchyStressMatrix(const Matrix<Real> & S_t, Matrix<Real> & sigma) { AKANTU_DEBUG_IN(); sigma.clear(); /// see Finite ekement formulations for large deformation dynamic analysis, /// Bathe et al. IJNME vol 9, 1975, page 364 ^t\tau for (UInt i = 0; i < dim; ++i) { for (UInt m = 0; m < dim; ++m) { for (UInt n = 0; n < dim; ++n) { sigma(i * dim + m, i * dim + n) = S_t(m, n); } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline Element Material::convertToLocalElement(const Element & global_element) const { UInt ge = global_element.element; #ifndef AKANTU_NDEBUG UInt model_mat_index = this->model->getMaterialByElement( global_element.type, global_element.ghost_type)(ge); UInt mat_index = this->model->getMaterialIndex(this->name); AKANTU_DEBUG_ASSERT(model_mat_index == mat_index, "Conversion of a global element in a local element for " "the wrong material " << this->name << std::endl); #endif UInt le = this->model->getMaterialLocalNumbering( global_element.type, global_element.ghost_type)(ge); Element tmp_quad(global_element.type, le, global_element.ghost_type, global_element.kind); return tmp_quad; } /* -------------------------------------------------------------------------- */ inline Element Material::convertToGlobalElement(const Element & local_element) const { UInt le = local_element.element; UInt ge = this->element_filter(local_element.type, local_element.ghost_type)(le); Element tmp_quad(local_element.type, ge, local_element.ghost_type, local_element.kind); return tmp_quad; } /* -------------------------------------------------------------------------- */ inline IntegrationPoint Material::convertToLocalPoint(const IntegrationPoint & global_point) const { const FEEngine & fem = this->model->getFEEngine(); UInt nb_quad = fem.getNbIntegrationPoints(global_point.type); Element el = this->convertToLocalElement(static_cast<const Element &>(global_point)); IntegrationPoint tmp_quad(el, global_point.num_point, nb_quad); return tmp_quad; } /* -------------------------------------------------------------------------- */ inline IntegrationPoint Material::convertToGlobalPoint(const IntegrationPoint & local_point) const { const FEEngine & fem = this->model->getFEEngine(); UInt nb_quad = fem.getNbIntegrationPoints(local_point.type); Element el = this->convertToGlobalElement(static_cast<const Element &>(local_point)); IntegrationPoint tmp_quad(el, local_point.num_point, nb_quad); return tmp_quad; } /* -------------------------------------------------------------------------- */ inline UInt Material::getNbData(const Array<Element> & elements, const SynchronizationTag & tag) const { if (tag == _gst_smm_stress) { return (this->isFiniteDeformation() ? 3 : 1) * spatial_dimension * spatial_dimension * sizeof(Real) * this->getModel().getNbIntegrationPoints(elements); } return 0; } /* -------------------------------------------------------------------------- */ inline void Material::packData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) const { if (tag == _gst_smm_stress) { if (this->isFiniteDeformation()) { packElementDataHelper(piola_kirchhoff_2, buffer, elements); packElementDataHelper(gradu, buffer, elements); } packElementDataHelper(stress, buffer, elements); } } /* -------------------------------------------------------------------------- */ inline void Material::unpackData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) { if (tag == _gst_smm_stress) { if (this->isFiniteDeformation()) { unpackElementDataHelper(piola_kirchhoff_2, buffer, elements); unpackElementDataHelper(gradu, buffer, elements); } unpackElementDataHelper(stress, buffer, elements); } } /* -------------------------------------------------------------------------- */ inline const Parameter & Material::getParam(const ID & param) const { try { return get(param); } catch (...) { AKANTU_EXCEPTION("No parameter " << param << " in the material " << getID()); } } /* -------------------------------------------------------------------------- */ template <typename T> inline void Material::setParam(const ID & param, T value) { try { set<T>(param, value); } catch (...) { AKANTU_EXCEPTION("No parameter " << param << " in the material " << getID()); } updateInternalParameters(); } /* -------------------------------------------------------------------------- */ template <typename T> inline void Material::packElementDataHelper( const ElementTypeMapArray<T> & data_to_pack, CommunicationBuffer & buffer, const Array<Element> & elements, const ID & fem_id) const { DataAccessor::packElementalDataHelper<T>(data_to_pack, buffer, elements, true, model->getFEEngine(fem_id)); } /* -------------------------------------------------------------------------- */ template <typename T> inline void Material::unpackElementDataHelper( ElementTypeMapArray<T> & data_to_unpack, CommunicationBuffer & buffer, const Array<Element> & elements, const ID & fem_id) { DataAccessor::unpackElementalDataHelper<T>(data_to_unpack, buffer, elements, true, model->getFEEngine(fem_id)); } /* -------------------------------------------------------------------------- */ template <> inline void Material::registerInternal<Real>(InternalField<Real> & vect) { internal_vectors_real[vect.getID()] = &vect; } template <> inline void Material::registerInternal<UInt>(InternalField<UInt> & vect) { internal_vectors_uint[vect.getID()] = &vect; } template <> inline void Material::registerInternal<bool>(InternalField<bool> & vect) { internal_vectors_bool[vect.getID()] = &vect; } /* -------------------------------------------------------------------------- */ template <> inline void Material::unregisterInternal<Real>(InternalField<Real> & vect) { internal_vectors_real.erase(vect.getID()); } template <> inline void Material::unregisterInternal<UInt>(InternalField<UInt> & vect) { internal_vectors_uint.erase(vect.getID()); } template <> inline void Material::unregisterInternal<bool>(InternalField<bool> & vect) { internal_vectors_bool.erase(vect.getID()); } /* -------------------------------------------------------------------------- */ template <typename T> inline bool Material::isInternal(__attribute__((unused)) const ID & id, __attribute__((unused)) const ElementKind & element_kind) const { AKANTU_DEBUG_TO_IMPLEMENT(); } template <> inline bool Material::isInternal<Real>(const ID & id, const ElementKind & element_kind) const { std::map<ID, InternalField<Real> *>::const_iterator internal_array = internal_vectors_real.find(this->getID() + ":" + id); if (internal_array == internal_vectors_real.end() || internal_array->second->getElementKind() != element_kind) return false; return true; } /* -------------------------------------------------------------------------- */ template <typename T> inline ElementTypeMap<UInt> Material::getInternalDataPerElem(const ID & field_id, const ElementKind & element_kind) const { if (!this->template isInternal<T>(field_id, element_kind)) AKANTU_EXCEPTION("Cannot find internal field " << id << " in material " << this->name); const InternalField<T> & internal_field = this->template getInternal<T>(field_id); const FEEngine & fe_engine = internal_field.getFEEngine(); UInt nb_data_per_quad = internal_field.getNbComponent(); ElementTypeMap<UInt> res; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { typedef typename InternalField<T>::type_iterator type_iterator; type_iterator tit = internal_field.firstType(*gt); type_iterator tend = internal_field.lastType(*gt); for (; tit != tend; ++tit) { UInt nb_quadrature_points = fe_engine.getNbIntegrationPoints(*tit, *gt); res(*tit, *gt) = nb_data_per_quad * nb_quadrature_points; } } return res; } /* -------------------------------------------------------------------------- */ template <typename T> void Material::flattenInternal(const std::string & field_id, ElementTypeMapArray<T> & internal_flat, const GhostType ghost_type, ElementKind element_kind) const { if (!this->template isInternal<T>(field_id, element_kind)) AKANTU_EXCEPTION("Cannot find internal field " << id << " in material " << this->name); const InternalField<T> & internal_field = this->template getInternal<T>(field_id); const FEEngine & fe_engine = internal_field.getFEEngine(); const Mesh & mesh = fe_engine.getMesh(); typedef typename InternalField<T>::filter_type_iterator type_iterator; type_iterator tit = internal_field.filterFirstType(ghost_type); type_iterator tend = internal_field.filterLastType(ghost_type); for (; tit != tend; ++tit) { ElementType type = *tit; const Array<Real> & src_vect = internal_field(type, ghost_type); const Array<UInt> & filter = internal_field.getFilter(type, ghost_type); // total number of elements in the corresponding mesh UInt nb_element_dst = mesh.getNbElement(type, ghost_type); // number of element in the internal field UInt nb_element_src = filter.getSize(); // number of quadrature points per elem UInt nb_quad_per_elem = fe_engine.getNbIntegrationPoints(type); // number of data per quadrature point UInt nb_data_per_quad = internal_field.getNbComponent(); if (!internal_flat.exists(type, ghost_type)) { internal_flat.alloc(nb_element_dst * nb_quad_per_elem, nb_data_per_quad, type, ghost_type); } if (nb_element_src == 0) continue; // number of data per element UInt nb_data = nb_quad_per_elem * nb_data_per_quad; Array<Real> & dst_vect = internal_flat(type, ghost_type); dst_vect.resize(nb_element_dst * nb_quad_per_elem); Array<UInt>::const_scalar_iterator it = filter.begin(); Array<UInt>::const_scalar_iterator end = filter.end(); Array<Real>::const_vector_iterator it_src = src_vect.begin_reinterpret(nb_data, nb_element_src); Array<Real>::vector_iterator it_dst = dst_vect.begin_reinterpret(nb_data, nb_element_dst); for (; it != end; ++it, ++it_src) { it_dst[*it] = *it_src; } } } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_INLINE_IMPL_CC__ */ diff --git a/src/model/solid_mechanics/material_selector.hh b/src/model/solid_mechanics/material_selector.hh index 9f55a061f..603a250b9 100644 --- a/src/model/solid_mechanics/material_selector.hh +++ b/src/model/solid_mechanics/material_selector.hh @@ -1,147 +1,147 @@ /** * @file material_selector.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Thu Dec 17 2015 * * @brief class describing how to choose a material for a given element * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_SELECTOR_HH__ #define __AKANTU_MATERIAL_SELECTOR_HH__ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class SolidMechanicsModel; /** * main class to assign same or different materials for different * elements */ class MaterialSelector { public: MaterialSelector() : fallback_value(0) {} virtual ~MaterialSelector() {} virtual UInt operator()(__attribute__((unused)) const Element & element) { return fallback_value; } void setFallback(UInt f) { fallback_value = f; } protected: UInt fallback_value; }; /* -------------------------------------------------------------------------- */ /** * class that assigns the first material to regular elements by default */ class DefaultMaterialSelector : public MaterialSelector { public: DefaultMaterialSelector(const ElementTypeMapArray<UInt> & material_index) : material_index(material_index) {} UInt operator()(const Element & element) { try { DebugLevel dbl = debug::getDebugLevel(); debug::setDebugLevel(dblError); const Array<UInt> & mat_indexes = material_index(element.type, element.ghost_type); UInt mat = this->fallback_value; if (element.element < mat_indexes.getSize()) mat = mat_indexes(element.element); debug::setDebugLevel(dbl); return mat; } catch (...) { return MaterialSelector::operator()(element); } } private: const ElementTypeMapArray<UInt> & material_index; }; /* -------------------------------------------------------------------------- */ /** * Use elemental data to assign materials */ template <typename T> class ElementDataMaterialSelector : public MaterialSelector { public: ElementDataMaterialSelector(const ElementTypeMapArray<T> & element_data, const SolidMechanicsModel & model, UInt first_index = 1) : element_data(element_data), model(model), first_index(first_index) {} inline T elementData(const Element & element) { DebugLevel dbl = debug::getDebugLevel(); debug::setDebugLevel(dblError); T data = element_data(element.type, element.ghost_type)(element.element); debug::setDebugLevel(dbl); return data; } inline UInt operator()(const Element & element) { return MaterialSelector::operator()(element); } protected: /// list of element with the specified data (i.e. tag value) const ElementTypeMapArray<T> & element_data; /// the model that the materials belong const SolidMechanicsModel & model; /// first material index: equal to 1 if none specified UInt first_index; }; /* -------------------------------------------------------------------------- */ /** * class to use mesh data information to assign different materials * where name is the tag value: tag_0, tag_1 */ template <typename T> class MeshDataMaterialSelector : public ElementDataMaterialSelector<T> { public: MeshDataMaterialSelector(const std::string & name, const SolidMechanicsModel & model, UInt first_index = 1); }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_SELECTOR_HH__ */ diff --git a/src/model/solid_mechanics/material_selector_tmpl.hh b/src/model/solid_mechanics/material_selector_tmpl.hh index adf4bda9a..71083761f 100644 --- a/src/model/solid_mechanics/material_selector_tmpl.hh +++ b/src/model/solid_mechanics/material_selector_tmpl.hh @@ -1,70 +1,70 @@ /** * @file material_selector_tmpl.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Fri May 01 2015 * * @brief Implementation of the template MaterialSelector * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_SELECTOR_TMPL_HH__ #define __AKANTU_MATERIAL_SELECTOR_TMPL_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<typename T> MeshDataMaterialSelector<T>::MeshDataMaterialSelector(const std::string & name, const SolidMechanicsModel & model, UInt first_index): ElementDataMaterialSelector<T>(model.getMesh().getData<T>(name), model, first_index) {} /* -------------------------------------------------------------------------- */ template<> inline UInt ElementDataMaterialSelector<std::string>::operator() (const Element & element) { try { std::string material_name = this->elementData(element); return model.getMaterialIndex(material_name); } catch (...) { return MaterialSelector::operator()(element); } } /* -------------------------------------------------------------------------- */ template<> inline UInt ElementDataMaterialSelector<UInt>::operator() (const Element & element) { try { return this->elementData(element) - first_index; } catch (...) { return MaterialSelector::operator()(element); } } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_SELECTOR_TMPL_HH__ */ diff --git a/src/model/solid_mechanics/materials/internal_field.hh b/src/model/solid_mechanics/materials/internal_field.hh index ef2c3ecc2..25cd18f86 100644 --- a/src/model/solid_mechanics/materials/internal_field.hh +++ b/src/model/solid_mechanics/materials/internal_field.hh @@ -1,257 +1,257 @@ /** * @file internal_field.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Dec 08 2015 * * @brief Material internal properties * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "element_type_map.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_INTERNAL_FIELD_HH__ #define __AKANTU_INTERNAL_FIELD_HH__ -__BEGIN_AKANTU__ +namespace akantu { class Material; class FEEngine; /** * class for the internal fields of materials * to store values for each quadrature */ template <typename T> class InternalField : public ElementTypeMapArray<T> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: InternalField(const ID & id, Material & material); virtual ~InternalField(); /// This constructor is only here to let cohesive elements compile InternalField(const ID & id, Material & material, FEEngine & fem, const ElementTypeMapArray<UInt> & element_filter); /// More general constructor InternalField(const ID & id, Material & material, UInt dim, FEEngine & fem, const ElementTypeMapArray<UInt> & element_filter); InternalField(const ID & id, const InternalField<T> & other); private: InternalField operator=(__attribute__((unused)) const InternalField & other){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// function to reset the FEEngine for the internal field virtual void setFEEngine(FEEngine & fe_engine); /// function to reset the element kind for the internal virtual void setElementKind(ElementKind element_kind); /// initialize the field to a given number of component virtual void initialize(UInt nb_component); /// activate the history of this field virtual void initializeHistory(); /// resize the arrays and set the new element to 0 virtual void resize(); /// set the field to a given value v virtual void setDefaultValue(const T & v); /// reset all the fields to the default value virtual void reset(); /// save the current values in the history virtual void saveCurrentValues(); /// remove the quadrature points corresponding to suppressed elements virtual void removeIntegrationPoints(const ElementTypeMapArray<UInt> & new_numbering); /// print the content virtual void printself(std::ostream & stream, int indent = 0) const; /// get the default value inline operator T() const; virtual FEEngine & getFEEngine() { return *fem; } virtual const FEEngine & getFEEngine() const { return *fem; } /// AKANTU_GET_MACRO(FEEngine, *fem, FEEngine &); protected: /// initialize the arrays in the ElementTypeMapArray<T> void internalInitialize(UInt nb_component); /// set the values for new internals virtual void setArrayValues(T * begin, T * end); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: typedef typename ElementTypeMapArray<T>::type_iterator type_iterator; typedef typename ElementTypeMapArray<UInt>::type_iterator filter_type_iterator; /// get the type iterator on all types contained in the internal field type_iterator firstType(const GhostType & ghost_type = _not_ghost) const { return ElementTypeMapArray<T>::firstType(this->spatial_dimension, ghost_type, this->element_kind); } /// get the type iterator on the last type contained in the internal field type_iterator lastType(const GhostType & ghost_type = _not_ghost) const { return ElementTypeMapArray<T>::lastType(this->spatial_dimension, ghost_type, this->element_kind); } /// get the type iterator on all types contained in the internal field filter_type_iterator filterFirstType(const GhostType & ghost_type = _not_ghost) const { return this->element_filter.firstType(this->spatial_dimension, ghost_type, this->element_kind); } /// get the type iterator on the last type contained in the internal field filter_type_iterator filterLastType(const GhostType & ghost_type = _not_ghost) const { return this->element_filter.lastType(this->spatial_dimension, ghost_type, this->element_kind); } /// get the array for a given type of the element_filter const Array<UInt> getFilter(const ElementType & type, const GhostType & ghost_type = _not_ghost) const { return this->element_filter(type, ghost_type); } /// get the Array corresponding to the type en ghost_type specified virtual Array<T> & operator()(const ElementType & type, const GhostType & ghost_type = _not_ghost) { return ElementTypeMapArray<T>::operator()(type, ghost_type); } virtual const Array<T> & operator()(const ElementType & type, const GhostType & ghost_type = _not_ghost) const { return ElementTypeMapArray<T>::operator()(type, ghost_type); } virtual Array<T> & previous(const ElementType & type, const GhostType & ghost_type = _not_ghost) { AKANTU_DEBUG_ASSERT(previous_values != NULL, "The history of the internal " << this->getID() << " has not been activated"); return this->previous_values->operator()(type, ghost_type); } virtual const Array<T> & previous(const ElementType & type, const GhostType & ghost_type = _not_ghost) const { AKANTU_DEBUG_ASSERT(previous_values != NULL, "The history of the internal " << this->getID() << " has not been activated"); return this->previous_values->operator()(type, ghost_type); } virtual InternalField<T> & previous() { AKANTU_DEBUG_ASSERT(previous_values != NULL, "The history of the internal " << this->getID() << " has not been activated"); return *(this->previous_values); } virtual const InternalField<T> & previous() const { AKANTU_DEBUG_ASSERT(previous_values != NULL, "The history of the internal " << this->getID() << " has not been activated"); return *(this->previous_values); } /// check if the history is used or not bool hasHistory() const { return (previous_values != NULL); } /// get the kind treated by the internal const ElementKind & getElementKind() const { return element_kind; } /// return the number of components UInt getNbComponent() const { return nb_component; } /// return the spatial dimension corresponding to the internal element type /// loop filter UInt getSpatialDimension() const { return this->spatial_dimension; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// the material for which this is an internal parameter Material & material; /// the fem containing the mesh and the element informations FEEngine * fem; /// Element filter if needed const ElementTypeMapArray<UInt> & element_filter; /// default value T default_value; /// spatial dimension of the element to consider UInt spatial_dimension; /// ElementKind of the element to consider ElementKind element_kind; /// Number of component of the internal field UInt nb_component; /// Is the field initialized bool is_init; /// previous values InternalField<T> * previous_values; }; /// standard output stream operator template <typename T> inline std::ostream & operator<<(std::ostream & stream, const InternalField<T> & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_INTERNAL_FIELD_HH__ */ diff --git a/src/model/solid_mechanics/materials/internal_field_tmpl.hh b/src/model/solid_mechanics/materials/internal_field_tmpl.hh index 074fdf1e7..156bd55e7 100644 --- a/src/model/solid_mechanics/materials/internal_field_tmpl.hh +++ b/src/model/solid_mechanics/materials/internal_field_tmpl.hh @@ -1,320 +1,320 @@ /** * @file internal_field_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Tue Dec 08 2015 * * @brief Material internal properties * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_INTERNAL_FIELD_TMPL_HH__ #define __AKANTU_INTERNAL_FIELD_TMPL_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <typename T> InternalField<T>::InternalField(const ID & id, Material & material) : ElementTypeMapArray<T>(id, material.getID(), material.getMemoryID()), material(material), fem(&(material.getModel().getFEEngine())), element_filter(material.getElementFilter()), default_value(T()), spatial_dimension(material.getModel().getSpatialDimension()), element_kind(_ek_regular), nb_component(0), is_init(false), previous_values(NULL) {} /* -------------------------------------------------------------------------- */ template <typename T> InternalField<T>::InternalField( const ID & id, Material & material, FEEngine & fem, const ElementTypeMapArray<UInt> & element_filter) : ElementTypeMapArray<T>(id, material.getID(), material.getMemoryID()), material(material), fem(&fem), element_filter(element_filter), default_value(T()), spatial_dimension(material.getSpatialDimension()), element_kind(_ek_regular), nb_component(0), is_init(false), previous_values(NULL) {} /* -------------------------------------------------------------------------- */ template <typename T> InternalField<T>::InternalField( const ID & id, Material & material, UInt dim, FEEngine & fem, const ElementTypeMapArray<UInt> & element_filter) : ElementTypeMapArray<T>(id, material.getID(), material.getMemoryID()), material(material), fem(&fem), element_filter(element_filter), default_value(T()), spatial_dimension(dim), element_kind(_ek_regular), nb_component(0), is_init(false), previous_values(NULL) {} /* -------------------------------------------------------------------------- */ template <typename T> InternalField<T>::InternalField(const ID & id, const InternalField<T> & other) : ElementTypeMapArray<T>(id, other.material.getID(), other.material.getMemoryID()), material(other.material), fem(other.fem), element_filter(other.element_filter), default_value(other.default_value), spatial_dimension(other.spatial_dimension), element_kind(other.element_kind), nb_component(other.nb_component), is_init(false), previous_values(NULL) { AKANTU_DEBUG_ASSERT(other.is_init, "Cannot create a copy of a non initialized field"); this->internalInitialize(this->nb_component); } /* -------------------------------------------------------------------------- */ template <typename T> InternalField<T>::~InternalField() { if (this->is_init) { this->material.unregisterInternal(*this); } delete previous_values; } /* -------------------------------------------------------------------------- */ template <typename T> void InternalField<T>::setFEEngine(FEEngine & fe_engine) { this->fem = &fe_engine; } /* -------------------------------------------------------------------------- */ template <typename T> void InternalField<T>::setElementKind(ElementKind element_kind) { this->element_kind = element_kind; } /* -------------------------------------------------------------------------- */ template <typename T> void InternalField<T>::initialize(UInt nb_component) { internalInitialize(nb_component); } /* -------------------------------------------------------------------------- */ template <typename T> void InternalField<T>::initializeHistory() { if (!previous_values) previous_values = new InternalField<T>("previous_" + this->getID(), *this); } /* -------------------------------------------------------------------------- */ template <typename T> void InternalField<T>::resize() { if (!this->is_init) return; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { filter_type_iterator it = this->filterFirstType(*gt); filter_type_iterator end = this->filterLastType(*gt); for (; it != end; ++it) { UInt nb_element = this->element_filter(*it, *gt).getSize(); UInt nb_quadrature_points = this->fem->getNbIntegrationPoints(*it, *gt); UInt new_size = nb_element * nb_quadrature_points; UInt old_size = 0; Array<T> * vect = NULL; if (this->exists(*it, *gt)) { vect = &(this->operator()(*it, *gt)); old_size = vect->getSize(); vect->resize(new_size); } else { vect = &(this->alloc(nb_element * nb_quadrature_points, nb_component, *it, *gt)); } this->setArrayValues(vect->storage() + old_size * vect->getNbComponent(), vect->storage() + new_size * vect->getNbComponent()); } } } /* -------------------------------------------------------------------------- */ template <typename T> void InternalField<T>::setDefaultValue(const T & value) { this->default_value = value; this->reset(); } /* -------------------------------------------------------------------------- */ template <typename T> void InternalField<T>::reset() { for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { type_iterator it = this->firstType(*gt); type_iterator end = this->lastType(*gt); for (; it != end; ++it) { Array<T> & vect = this->operator()(*it, *gt); vect.clear(); this->setArrayValues(vect.storage(), vect.storage() + vect.getSize() * vect.getNbComponent()); } } } /* -------------------------------------------------------------------------- */ template <typename T> void InternalField<T>::internalInitialize(UInt nb_component) { if (!this->is_init) { this->nb_component = nb_component; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { filter_type_iterator it = this->filterFirstType(*gt); filter_type_iterator end = this->filterLastType(*gt); for (; it != end; ++it) { UInt nb_element = this->element_filter(*it, *gt).getSize(); UInt nb_quadrature_points = this->fem->getNbIntegrationPoints(*it, *gt); if (this->exists(*it, *gt)) this->operator()(*it, *gt).resize(nb_element * nb_quadrature_points); else this->alloc(nb_element * nb_quadrature_points, nb_component, *it, *gt); } } this->material.registerInternal(*this); this->is_init = true; } this->reset(); if (this->previous_values) this->previous_values->internalInitialize(nb_component); } /* -------------------------------------------------------------------------- */ template <typename T> void InternalField<T>::setArrayValues(T * begin, T * end) { for (; begin < end; ++begin) *begin = this->default_value; } /* -------------------------------------------------------------------------- */ template <typename T> void InternalField<T>::saveCurrentValues() { AKANTU_DEBUG_ASSERT(this->previous_values != NULL, "The history of the internal " << this->getID() << " has not been activated"); if (!this->is_init) return; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { type_iterator it = this->firstType(*gt); type_iterator end = this->lastType(*gt); for (; it != end; ++it) { this->previous_values->operator()(*it, *gt) .copy(this->operator()(*it, *gt)); } } } /* -------------------------------------------------------------------------- */ template <typename T> void InternalField<T>::removeIntegrationPoints( const ElementTypeMapArray<UInt> & new_numbering) { for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { ElementTypeMapArray<UInt>::type_iterator it = new_numbering.firstType(_all_dimensions, *gt, _ek_not_defined); ElementTypeMapArray<UInt>::type_iterator end = new_numbering.lastType(_all_dimensions, *gt, _ek_not_defined); for (; it != end; ++it) { ElementType type = *it; if (this->exists(type, *gt)) { Array<T> & vect = this->operator()(type, *gt); if (!vect.getSize()) continue; const Array<UInt> & renumbering = new_numbering(type, *gt); UInt nb_quad_per_elem = fem->getNbIntegrationPoints(type, *gt); UInt nb_component = vect.getNbComponent(); Array<T> tmp(renumbering.getSize() * nb_quad_per_elem, nb_component); AKANTU_DEBUG_ASSERT( tmp.getSize() == vect.getSize(), "Something strange append some mater was created from nowhere!!"); AKANTU_DEBUG_ASSERT( tmp.getSize() == vect.getSize(), "Something strange append some mater was created or disappeared in " << vect.getID() << "(" << vect.getSize() << "!=" << tmp.getSize() << ") " "!!"); UInt new_size = 0; for (UInt i = 0; i < renumbering.getSize(); ++i) { UInt new_i = renumbering(i); if (new_i != UInt(-1)) { memcpy(tmp.storage() + new_i * nb_component * nb_quad_per_elem, vect.storage() + i * nb_component * nb_quad_per_elem, nb_component * nb_quad_per_elem * sizeof(T)); ++new_size; } } tmp.resize(new_size * nb_quad_per_elem); vect.copy(tmp); } } } } /* -------------------------------------------------------------------------- */ template <typename T> void InternalField<T>::printself(std::ostream & stream, int indent) const { stream << "InternalField [ " << this->getID(); #if !defined(AKANTU_NDEBUG) if (AKANTU_DEBUG_TEST(dblDump)) { stream << std::endl; ElementTypeMapArray<T>::printself(stream, indent + 3); } else { #endif stream << " {" << this->getData(_not_ghost).size() << " types - " << this->getData(_ghost).size() << " ghost types" << "}"; #if !defined(AKANTU_NDEBUG) } #endif stream << " ]"; } /* -------------------------------------------------------------------------- */ template <> inline void ParameterTyped<InternalField<Real> >::setAuto( const ParserParameter & in_param) { Parameter::setAuto(in_param); Real r = in_param; param.setDefaultValue(r); } /* -------------------------------------------------------------------------- */ template <typename T> inline InternalField<T>::operator T() const { return default_value; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_INTERNAL_FIELD_TMPL_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_cohesive/cohesive_internal_field.hh b/src/model/solid_mechanics/materials/material_cohesive/cohesive_internal_field.hh index b8835bf54..241604669 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/cohesive_internal_field.hh +++ b/src/model/solid_mechanics/materials/material_cohesive/cohesive_internal_field.hh @@ -1,70 +1,70 @@ /** * @file cohesive_internal_field.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 08 2015 * * @brief Internal field for cohesive elements * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "internal_field.hh" #ifndef __AKANTU_COHESIVE_INTERNAL_FIELD_HH__ #define __AKANTU_COHESIVE_INTERNAL_FIELD_HH__ -__BEGIN_AKANTU__ +namespace akantu { /// internal field class for cohesive materials template<typename T> class CohesiveInternalField : public InternalField<T> { public: CohesiveInternalField(const ID & id, Material & material); virtual ~CohesiveInternalField(); /// initialize the field to a given number of component void initialize(UInt nb_component); private: CohesiveInternalField operator=(__attribute__((unused)) const CohesiveInternalField & other) {}; }; /* -------------------------------------------------------------------------- */ /* Facet Internal Field */ /* -------------------------------------------------------------------------- */ template<typename T> class FacetInternalField : public InternalField<T> { public: FacetInternalField(const ID & id, Material & material); virtual ~FacetInternalField(); /// initialize the field to a given number of component void initialize(UInt nb_component); }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_COHESIVE_INTERNAL_FIELD_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_cohesive/cohesive_internal_field_tmpl.hh b/src/model/solid_mechanics/materials/material_cohesive/cohesive_internal_field_tmpl.hh index 85c8c5090..a8e3aef34 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/cohesive_internal_field_tmpl.hh +++ b/src/model/solid_mechanics/materials/material_cohesive/cohesive_internal_field_tmpl.hh @@ -1,94 +1,94 @@ /** * @file cohesive_internal_field_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Thu Jan 21 2016 * * @brief implementation of the cohesive internal field * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_COHESIVE_INTERNAL_FIELD_TMPL_HH__ #define __AKANTU_COHESIVE_INTERNAL_FIELD_TMPL_HH__ -__BEGIN_AKANTU__ +namespace akantu { template <typename T> CohesiveInternalField<T>::CohesiveInternalField(const ID & id, Material & material) : InternalField<T>( id, material, material.getModel().getFEEngine("CohesiveFEEngine"), dynamic_cast<MaterialCohesive &>(material).getElementFilter()) { this->element_kind = _ek_cohesive; } template <typename T> CohesiveInternalField<T>::~CohesiveInternalField() {} template <typename T> void CohesiveInternalField<T>::initialize(UInt nb_component) { this->internalInitialize(nb_component); } /* -------------------------------------------------------------------------- */ template <typename T> FacetInternalField<T>::FacetInternalField(const ID & id, Material & material) : InternalField<T>( id, material, material.getModel().getFEEngine("FacetsFEEngine"), dynamic_cast<MaterialCohesive &>(material).getFacetFilter()) { this->spatial_dimension -= 1; this->element_kind = _ek_regular; } template <typename T> FacetInternalField<T>::~FacetInternalField() {} template <typename T> void FacetInternalField<T>::initialize(UInt nb_component) { this->internalInitialize(nb_component); } /* -------------------------------------------------------------------------- */ template <> inline void ParsableParamTyped<RandomInternalField<Real, FacetInternalField> >::parseParam( const ParserParameter & in_param) { ParsableParam::parseParam(in_param); RandomParameter<Real> r = in_param; param.setRandomDistribution(r); } /* -------------------------------------------------------------------------- */ template <> inline void ParsableParamTyped<RandomInternalField<Real, CohesiveInternalField> >:: parseParam(const ParserParameter & in_param) { ParsableParam::parseParam(in_param); RandomParameter<Real> r = in_param; param.setRandomDistribution(r); } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_COHESIVE_INTERNAL_FIELD_TMPL_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.cc index eb91a47ec..27d48cc8d 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.cc @@ -1,211 +1,211 @@ /** * @file material_cohesive_bilinear.cc * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Feb 22 2012 * @date last modification: Thu Oct 15 2015 * * @brief Bilinear cohesive constitutive law * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_cohesive_bilinear.hh" #include "solid_mechanics_model_cohesive.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialCohesiveBilinear<spatial_dimension>::MaterialCohesiveBilinear(SolidMechanicsModel & model, const ID & id) : MaterialCohesiveLinear<spatial_dimension>(model, id) { AKANTU_DEBUG_IN(); this->registerParam("delta_0", delta_0, Real(0.), _pat_parsable | _pat_readable, "Elastic limit displacement"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveBilinear<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); this->sigma_c_eff.setRandomDistribution(this->sigma_c.getRandomParameter()); MaterialCohesiveLinear<spatial_dimension>::initMaterial(); this->delta_max .setDefaultValue(delta_0); this->insertion_stress.setDefaultValue(0); this->delta_max .reset(); this->insertion_stress.reset(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveBilinear<spatial_dimension>::onElementsAdded(const Array<Element> & element_list, const NewElementsEvent & event) { AKANTU_DEBUG_IN(); MaterialCohesiveLinear<spatial_dimension>::onElementsAdded(element_list, event); bool scale_traction = false; // don't scale sigma_c if volume_s hasn't been specified by the user if (!Math::are_float_equal(this->volume_s, 0.)) scale_traction = true; Array<Element>::const_scalar_iterator el_it = element_list.begin(); Array<Element>::const_scalar_iterator el_end = element_list.end(); for (; el_it != el_end; ++el_it) { // filter not ghost cohesive elements if (el_it->ghost_type != _not_ghost || el_it->kind != _ek_cohesive) continue; UInt index = el_it->element; ElementType type = el_it->type; UInt nb_element = this->model->getMesh().getNbElement(type); UInt nb_quad_per_element = this->fem_cohesive->getNbIntegrationPoints(type); Array<Real>::vector_iterator sigma_c_begin = this->sigma_c_eff(type).begin_reinterpret(nb_quad_per_element, nb_element); Vector<Real> sigma_c_vec = sigma_c_begin[index]; Array<Real>::vector_iterator delta_c_begin = this->delta_c_eff(type).begin_reinterpret(nb_quad_per_element, nb_element); Vector<Real> delta_c_vec = delta_c_begin[index]; if (scale_traction) scaleTraction(*el_it, sigma_c_vec); /** * Recompute sigma_c as * @f$ {\sigma_c}_\textup{new} = * \frac{{\sigma_c}_\textup{old} \delta_c} {\delta_c - \delta_0} @f$ */ for (UInt q = 0; q < nb_quad_per_element; ++q) { delta_c_vec(q) = 2 * this->G_c / sigma_c_vec(q); if (delta_c_vec(q) - delta_0 < Math::getTolerance()) AKANTU_DEBUG_ERROR("delta_0 = " << delta_0 << " must be lower than delta_c = " << delta_c_vec(q) << ", modify your material file"); sigma_c_vec(q) *= delta_c_vec(q) / (delta_c_vec(q) - delta_0); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveBilinear<spatial_dimension>::scaleTraction(const Element & el, Vector<Real> & sigma_c_vec) { AKANTU_DEBUG_IN(); Real base_sigma_c = this->sigma_c_eff; const Mesh & mesh_facets = this->model->getMeshFacets(); const FEEngine & fe_engine = this->model->getFEEngine(); Array<Element>::const_vector_iterator coh_element_to_facet_begin = mesh_facets.getSubelementToElement(el.type).begin(2); const Vector<Element> & coh_element_to_facet = coh_element_to_facet_begin[el.element]; // compute bounding volume Real volume = 0; // loop over facets for (UInt f = 0; f < 2; ++f) { const Element & facet = coh_element_to_facet(f); const Array< std::vector<Element> > & facet_to_element = mesh_facets.getElementToSubelement(facet.type, facet.ghost_type); const std::vector<Element> & element_list = facet_to_element(facet.element); std::vector<Element>::const_iterator elem = element_list.begin(); std::vector<Element>::const_iterator elem_end = element_list.end(); // loop over elements connected to each facet for (; elem != elem_end; ++elem) { // skip cohesive elements and dummy elements if (*elem == ElementNull || elem->kind == _ek_cohesive) continue; // unit vector for integration in order to obtain the volume UInt nb_quadrature_points = fe_engine.getNbIntegrationPoints(elem->type); Vector<Real> unit_vector(nb_quadrature_points, 1); volume += fe_engine.integrate(unit_vector, elem->type, elem->element, elem->ghost_type); } } // scale sigma_c sigma_c_vec -= base_sigma_c; sigma_c_vec *= std::pow(this->volume_s / volume, 1. / this->m_s); sigma_c_vec += base_sigma_c; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveBilinear<spatial_dimension>::computeTraction(const Array<Real> & normal, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialCohesiveLinear<spatial_dimension>::computeTraction(normal, el_type, ghost_type); // adjust damage Array<Real>::scalar_iterator delta_c_it = this->delta_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_max_it = this->delta_max(el_type, ghost_type).begin(); Array<Real>::scalar_iterator damage_it = this->damage(el_type, ghost_type).begin(); Array<Real>::scalar_iterator damage_end = this->damage(el_type, ghost_type).end(); for (; damage_it != damage_end; ++damage_it, ++delta_max_it, ++delta_c_it) { *damage_it = std::max((*delta_max_it - delta_0) / (*delta_c_it - delta_0), Real(0.)); *damage_it = std::min(*damage_it, Real(1.)); } } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialCohesiveBilinear); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.hh b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.hh index 17e11e33c..241d81e97 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.hh +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.hh @@ -1,113 +1,113 @@ /** * @file material_cohesive_bilinear.hh * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief Bilinear cohesive constitutive law * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_cohesive_linear.hh" #ifndef __AKANTU_MATERIAL_COHESIVE_BILINEAR_HH__ #define __AKANTU_MATERIAL_COHESIVE_BILINEAR_HH__ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /** * Cohesive material bilinear * * parameters in the material files : * - delta_0 : elastic limit displacement (default: 0) * - sigma_c : critical stress sigma_c (default: 0) * - beta : weighting parameter for sliding and normal opening (default: 0) * - G_cI : fracture energy for mode I (default: 0) * - G_cII : fracture energy for mode II (default: 0) * - penalty : stiffness in compression to prevent penetration */ template<UInt spatial_dimension> class MaterialCohesiveBilinear : public MaterialCohesiveLinear<spatial_dimension> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialCohesiveBilinear(SolidMechanicsModel & model, const ID & id = ""); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the material computed parameter virtual void initMaterial(); /// set material parameters for new elements virtual void onElementsAdded(const Array<Element> & element_list, const NewElementsEvent & event); protected: /// constitutive law void computeTraction(const Array<Real> & normal, ElementType el_type, GhostType ghost_type = _not_ghost); /** * Scale traction sigma_c according to the volume of the * two elements surrounding an element */ void scaleTraction(const Element & el, Vector<Real> & sigma_c_vec); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// elastic limit displacement Real delta_0; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "material_cohesive_elastic_inline_impl.cc" -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_COHESIVE_BILINEAR_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.cc index 69749adec..c1af5b1bf 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.cc @@ -1,365 +1,365 @@ /** * @file material_cohesive_exponential.cc * * @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Mon Jul 09 2012 * @date last modification: Tue Aug 04 2015 * * @brief Exponential irreversible cohesive law of mixed mode loading * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_cohesive_exponential.hh" #include "solid_mechanics_model.hh" #include "sparse_matrix.hh" #include "dof_synchronizer.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialCohesiveExponential<spatial_dimension>::MaterialCohesiveExponential(SolidMechanicsModel & model, const ID & id) : MaterialCohesive(model,id) { AKANTU_DEBUG_IN(); this->registerParam("beta", beta, Real(0.), _pat_parsable, "Beta parameter"); this->registerParam("exponential_penalty", exp_penalty, true, _pat_parsable, "Is contact penalty following the exponential law?"); this->registerParam("contact_tangent", contact_tangent, Real(1.0), _pat_parsable, "Ratio of contact tangent over the initial exponential tangent"); // this->initInternalArray(delta_max, 1, _ek_cohesive); use_previous_delta_max=true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveExponential<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialCohesive::initMaterial(); if ((exp_penalty) && (contact_tangent != 1)){ contact_tangent = 1; AKANTU_DEBUG_WARNING("The parsed paramter <contact_tangent> is forced to 1.0 when the contact penalty follows the exponential law"); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveExponential<spatial_dimension>::computeTraction(const Array<Real> & normal, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array<Real>::vector_iterator traction_it = tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator opening_it = opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::const_vector_iterator normal_it = normal.begin(spatial_dimension); Array<Real>::vector_iterator traction_end = tractions(el_type, ghost_type).end(spatial_dimension); Array<Real>::iterator<Real> delta_max_it = delta_max(el_type, ghost_type).begin(); Array<Real>::iterator<Real> delta_max_prev_it = delta_max.previous(el_type, ghost_type).begin(); /// compute scalars Real beta2 = beta * beta; /// loop on each quadrature point for (; traction_it != traction_end; ++traction_it, ++opening_it, ++normal_it, ++delta_max_it, ++delta_max_prev_it) { /// compute normal and tangential opening vectors Real normal_opening_norm = opening_it->dot(*normal_it); Vector<Real> normal_opening(spatial_dimension); normal_opening = (*normal_it); normal_opening *= normal_opening_norm; Vector<Real> tangential_opening(spatial_dimension); tangential_opening = *opening_it; tangential_opening -= normal_opening; Real tangential_opening_norm = tangential_opening.norm(); /** * compute effective opening displacement * @f$ \delta = \sqrt{ * \beta^2 \Delta_t^2 + \Delta_n^2 } @f$ */ Real delta = tangential_opening_norm; delta *= delta * beta2; delta += normal_opening_norm * normal_opening_norm; delta = sqrt(delta); if ((normal_opening_norm < 0) && (std::abs(normal_opening_norm) > Math::getTolerance())) { Vector<Real> op_n(*normal_it); op_n *= normal_opening_norm; Vector<Real> delta_s(*opening_it); delta_s -= op_n; delta = tangential_opening_norm * beta; computeCoupledTraction(*traction_it, *normal_it, delta, delta_s, *delta_max_it, *delta_max_prev_it); computeCompressiveTraction(*traction_it, *normal_it, normal_opening_norm, *opening_it); } else computeCoupledTraction(*traction_it, *normal_it, delta, *opening_it, *delta_max_it, *delta_max_prev_it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveExponential<spatial_dimension>::computeCoupledTraction(Vector<Real> & tract, const Vector<Real> & normal, Real delta, const Vector<Real> & opening, Real & delta_max_new, Real delta_max) { AKANTU_DEBUG_IN(); /// full damage case if (std::abs(delta) < Math::getTolerance()) { /// set traction to zero tract.clear(); } else { /// element not fully damaged /** * Compute traction loading @f$ \mathbf{T} = * e \sigma_c \frac{\delta}{\delta_c} e^{-\delta/ \delta_c}@f$ */ /** * Compute traction unloading @f$ \mathbf{T} = * \frac{t_{max}}{\delta_{max}} \delta @f$ */ Real beta2 = beta * beta; Real normal_open_norm = opening.dot(normal); Vector<Real> op_n_n(spatial_dimension); op_n_n = normal; op_n_n *= (1 - beta2); op_n_n *= normal_open_norm; tract = beta2 * opening; tract += op_n_n; delta_max_new = std::max(delta_max, delta); tract *= exp(1) * sigma_c * exp(-delta_max_new / delta_c) / delta_c; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveExponential<spatial_dimension>::computeCompressiveTraction(Vector<Real> & tract, const Vector<Real> & normal, Real delta_n, __attribute__((unused)) const Vector<Real> & opening) { Vector<Real> temp_tract(normal); if(exp_penalty) { temp_tract *= delta_n * exp(1) * sigma_c * exp(-delta_n / delta_c) / delta_c; } else { Real initial_tg = contact_tangent * exp(1) * sigma_c * delta_n / delta_c; temp_tract *= initial_tg; } tract += temp_tract; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveExponential<spatial_dimension>::computeTangentTraction(const ElementType & el_type, Array<Real> & tangent_matrix, const Array<Real> & normal, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real>::matrix_iterator tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension); Array<Real>::const_vector_iterator normal_it = normal.begin(spatial_dimension); Array<Real>::vector_iterator opening_it = opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::iterator<Real>delta_max_it = delta_max.previous(el_type, ghost_type).begin(); Real beta2 = beta * beta; /** * compute tangent matrix @f$ \frac{\partial \mathbf{t}} * {\partial \delta} = \hat{\mathbf{t}} \otimes * \frac{\partial (t/\delta)}{\partial \delta} * \frac{\hat{\mathbf{t}}}{\delta}+ \frac{t}{\delta} [ \beta^2 \mathbf{I} + * (1-\beta^2) (\mathbf{n} \otimes \mathbf{n})] @f$ **/ /** * In which @f$ * \frac{\partial(t/ \delta)}{\partial \delta} = * \left\{\begin{array} {l l} * -e \frac{\sigma_c}{\delta_c^2 }e^{-\delta / \delta_c} & \quad if * \delta \geq \delta_{max} \\ * 0 & \quad if \delta < \delta_{max}, \delta_n > 0 * \end{array}\right. @f$ **/ for (; tangent_it != tangent_end; ++tangent_it, ++normal_it, ++opening_it, ++ delta_max_it) { Real normal_opening_norm = opening_it->dot(*normal_it); Vector<Real> normal_opening(spatial_dimension); normal_opening = (*normal_it); normal_opening *= normal_opening_norm; Vector<Real> tangential_opening(spatial_dimension); tangential_opening = *opening_it; tangential_opening -= normal_opening; Real tangential_opening_norm = tangential_opening.norm(); Real delta = tangential_opening_norm; delta *= delta * beta2; delta += normal_opening_norm * normal_opening_norm; delta = sqrt(delta); if ((normal_opening_norm < 0) && (std::abs(normal_opening_norm) > Math::getTolerance())) { Vector<Real> op_n(*normal_it); op_n *= normal_opening_norm; Vector<Real> delta_s(*opening_it); delta_s -= op_n; delta = tangential_opening_norm * beta; computeCoupledTangent(*tangent_it, *normal_it, delta, delta_s, *delta_max_it); computeCompressivePenalty(*tangent_it, *normal_it, normal_opening_norm); } else computeCoupledTangent(*tangent_it, *normal_it, delta, *opening_it, *delta_max_it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveExponential<spatial_dimension>::computeCoupledTangent(Matrix<Real> & tangent, const Vector<Real> & normal, Real delta, const Vector<Real> & opening, Real delta_max_new) { AKANTU_DEBUG_IN(); Real beta2 = beta * beta; Matrix<Real> J(spatial_dimension,spatial_dimension); J.eye(beta2); if(std::abs(delta) < Math::getTolerance()){ delta = Math::getTolerance(); } Real opening_normal; opening_normal = opening.dot(normal); Vector<Real>delta_e(normal); delta_e *= opening_normal; delta_e *= (1 - beta2); delta_e += (beta2 * opening); Real exponent = exp(1 - delta / delta_c) * sigma_c / delta_c; Matrix<Real> first_term(spatial_dimension, spatial_dimension); first_term.outerProduct(normal, normal); first_term *= (1 - beta2); first_term += J; Matrix<Real>second_term(spatial_dimension, spatial_dimension); second_term.outerProduct(delta_e,delta_e); second_term /= delta; second_term /= delta_c; Matrix<Real>diff(first_term); diff -= second_term; tangent = diff; tangent *= exponent; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveExponential<spatial_dimension>::computeCompressivePenalty(Matrix<Real> & tangent, const Vector<Real> & normal, Real delta_n) { if (!exp_penalty) delta_n=0; Matrix<Real> n_outer_n(spatial_dimension,spatial_dimension); n_outer_n.outerProduct(normal,normal); Real normal_tg = contact_tangent * exp(1) * sigma_c * exp(-delta_n / delta_c) * (1 - delta_n / delta_c) / delta_c; n_outer_n *= normal_tg; tangent += n_outer_n; } INSTANTIATE_MATERIAL(MaterialCohesiveExponential); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.hh b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.hh index 11de18644..a5a83b6e6 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.hh +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.hh @@ -1,128 +1,128 @@ /** * @file material_cohesive_exponential.hh * * @author Fabian Barras <fabian.barras@epfl.ch> * @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Feb 06 2015 * * @brief Exponential irreversible cohesive law of mixed mode loading * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_cohesive.hh" #include "aka_common.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_COHESIVE_EXPONENTIAL_HH__ #define __AKANTU_MATERIAL_COHESIVE_EXPONENTIAL_HH__ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /** * Cohesive material Exponential damage * * parameters in the material files : * - sigma_c : critical stress sigma_c (default: 0) * - beta : weighting parameter for sliding and normal opening (default: 0) * - delta_c : critical opening (default: 0) */ template<UInt spatial_dimension> class MaterialCohesiveExponential : public MaterialCohesive { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialCohesiveExponential(SolidMechanicsModel & model, const ID & id = ""); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ protected: /// Initialization void initMaterial(); /// constitutive law void computeTraction(const Array<Real> & normal, ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the tangent stiffness matrix for an element type void computeTangentTraction(const ElementType & el_type, Array<Real> & tangent_matrix, const Array<Real> & normal, GhostType ghost_type = _not_ghost); private: void computeCoupledTraction(Vector<Real> & tract, const Vector<Real> & normal, Real delta, const Vector<Real> & opening, Real & delta_max_new, Real delta_max); void computeCompressiveTraction(Vector<Real> & tract, const Vector<Real> & normal, Real delta_n, const Vector<Real> & opening); void computeCoupledTangent(Matrix<Real> & tangent, const Vector<Real> & normal, Real delta, const Vector<Real> & opening, Real delta_max_new); void computeCompressivePenalty(Matrix<Real> & tangent, const Vector<Real> & normal, Real delta_n); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// beta parameter Real beta; /// contact penalty = initial slope ? bool exp_penalty; /// Ratio of contact tangent over the initial exponential tangent Real contact_tangent; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ // #include "material_cohesive_exponential_inline_impl.cc" -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_COHESIVE_EXPONENTIAL_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc index fb0f01b3e..0472fae90 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc @@ -1,701 +1,701 @@ /** * @file material_cohesive_linear.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Feb 22 2012 * @date last modification: Thu Jan 14 2016 * * @brief Linear irreversible cohesive law of mixed mode loading with * random stress definition for extrinsic type * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <algorithm> #include <numeric> /* -------------------------------------------------------------------------- */ #include "dof_synchronizer.hh" #include "material_cohesive_linear.hh" #include "solid_mechanics_model_cohesive.hh" #include "sparse_matrix.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialCohesiveLinear<spatial_dimension>::MaterialCohesiveLinear( SolidMechanicsModel & model, const ID & id) : MaterialCohesive(model, id), sigma_c_eff("sigma_c_eff", *this), delta_c_eff("delta_c_eff", *this), insertion_stress("insertion_stress", *this), opening_prec("opening_prec", *this), reduction_penalty("reduction_penalty", *this) { AKANTU_DEBUG_IN(); this->registerParam("beta", beta, Real(0.), _pat_parsable | _pat_readable, "Beta parameter"); this->registerParam("G_c", G_c, Real(0.), _pat_parsable | _pat_readable, "Mode I fracture energy"); this->registerParam("penalty", penalty, Real(0.), _pat_parsable | _pat_readable, "Penalty coefficient"); this->registerParam("volume_s", volume_s, Real(0.), _pat_parsable | _pat_readable, "Reference volume for sigma_c scaling"); this->registerParam("m_s", m_s, Real(1.), _pat_parsable | _pat_readable, "Weibull exponent for sigma_c scaling"); this->registerParam("kappa", kappa, Real(1.), _pat_parsable | _pat_readable, "Kappa parameter"); this->registerParam( "contact_after_breaking", contact_after_breaking, false, _pat_parsable | _pat_readable, "Activation of contact when the elements are fully damaged"); this->registerParam("max_quad_stress_insertion", max_quad_stress_insertion, false, _pat_parsable | _pat_readable, "Insertion of cohesive element when stress is high " "enough just on one quadrature point"); this->registerParam("recompute", recompute, false, _pat_parsable | _pat_modifiable, "recompute solution"); this->use_previous_delta_max = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialCohesive::initMaterial(); /// compute scalars beta2_kappa2 = beta * beta / kappa / kappa; beta2_kappa = beta * beta / kappa; if (Math::are_float_equal(beta, 0)) beta2_inv = 0; else beta2_inv = 1. / beta / beta; sigma_c_eff.initialize(1); delta_c_eff.initialize(1); insertion_stress.initialize(spatial_dimension); opening_prec.initialize(spatial_dimension); reduction_penalty.initialize(1); if (!Math::are_float_equal(delta_c, 0.)) delta_c_eff.setDefaultValue(delta_c); else delta_c_eff.setDefaultValue(2 * G_c / sigma_c); if (model->getIsExtrinsic()) scaleInsertionTraction(); opening_prec.initializeHistory(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::scaleInsertionTraction() { AKANTU_DEBUG_IN(); // do nothing if volume_s hasn't been specified by the user if (Math::are_float_equal(volume_s, 0.)) return; const Mesh & mesh_facets = model->getMeshFacets(); const FEEngine & fe_engine = model->getFEEngine(); const FEEngine & fe_engine_facet = model->getFEEngine("FacetsFEEngine"); // loop over facet type Mesh::type_iterator first = mesh_facets.firstType(spatial_dimension - 1); Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1); Real base_sigma_c = sigma_c; for (; first != last; ++first) { ElementType type_facet = *first; const Array<std::vector<Element> > & facet_to_element = mesh_facets.getElementToSubelement(type_facet); UInt nb_facet = facet_to_element.getSize(); UInt nb_quad_per_facet = fe_engine_facet.getNbIntegrationPoints(type_facet); // iterator to modify sigma_c for all the quadrature points of a facet Array<Real>::vector_iterator sigma_c_iterator = sigma_c(type_facet).begin_reinterpret(nb_quad_per_facet, nb_facet); for (UInt f = 0; f < nb_facet; ++f, ++sigma_c_iterator) { const std::vector<Element> & element_list = facet_to_element(f); // compute bounding volume Real volume = 0; std::vector<Element>::const_iterator elem = element_list.begin(); std::vector<Element>::const_iterator elem_end = element_list.end(); for (; elem != elem_end; ++elem) { if (*elem == ElementNull) continue; // unit vector for integration in order to obtain the volume UInt nb_quadrature_points = fe_engine.getNbIntegrationPoints(elem->type); Vector<Real> unit_vector(nb_quadrature_points, 1); volume += fe_engine.integrate(unit_vector, elem->type, elem->element, elem->ghost_type); } // scale sigma_c *sigma_c_iterator -= base_sigma_c; *sigma_c_iterator *= std::pow(volume_s / volume, 1. / m_s); *sigma_c_iterator += base_sigma_c; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::checkInsertion( bool check_only) { AKANTU_DEBUG_IN(); const Mesh & mesh_facets = model->getMeshFacets(); CohesiveElementInserter & inserter = model->getElementInserter(); Real tolerance = Math::getTolerance(); Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1); Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1); for (; it != last; ++it) { ElementType type_facet = *it; ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet); const Array<bool> & facets_check = inserter.getCheckFacets(type_facet); Array<bool> & f_insertion = inserter.getInsertionFacets(type_facet); Array<UInt> & f_filter = facet_filter(type_facet); Array<Real> & sig_c_eff = sigma_c_eff(type_cohesive); Array<Real> & del_c = delta_c_eff(type_cohesive); Array<Real> & ins_stress = insertion_stress(type_cohesive); Array<Real> & trac_old = tractions_old(type_cohesive); Array<Real> & open_prec = opening_prec(type_cohesive); Array<bool> & red_penalty = reduction_penalty(type_cohesive); const Array<Real> & f_stress = model->getStressOnFacets(type_facet); const Array<Real> & sigma_lim = sigma_c(type_facet); Real max_ratio = 0.; UInt index_f = 0; UInt index_filter = 0; UInt nn = 0; UInt nb_quad_facet = model->getFEEngine("FacetsFEEngine").getNbIntegrationPoints(type_facet); UInt nb_quad_cohesive = model->getFEEngine("CohesiveFEEngine") .getNbIntegrationPoints(type_cohesive); AKANTU_DEBUG_ASSERT(nb_quad_cohesive == nb_quad_facet, "The cohesive element and the corresponding facet do " "not have the same numbers of integration points"); UInt nb_facet = f_filter.getSize(); // if (nb_facet == 0) continue; Array<Real>::const_iterator<Real> sigma_lim_it = sigma_lim.begin(); Matrix<Real> stress_tmp(spatial_dimension, spatial_dimension); Matrix<Real> normal_traction(spatial_dimension, nb_quad_facet); Vector<Real> stress_check(nb_quad_facet); UInt sp2 = spatial_dimension * spatial_dimension; const Array<Real> & tangents = model->getTangents(type_facet); const Array<Real> & normals = model->getFEEngine("FacetsFEEngine") .getNormalsOnIntegrationPoints(type_facet); Array<Real>::const_vector_iterator normal_begin = normals.begin(spatial_dimension); Array<Real>::const_vector_iterator tangent_begin = tangents.begin(tangents.getNbComponent()); Array<Real>::const_matrix_iterator facet_stress_begin = f_stress.begin(spatial_dimension, spatial_dimension * 2); std::vector<Real> new_sigmas; std::vector<Vector<Real> > new_normal_traction; std::vector<Real> new_delta_c; // loop over each facet belonging to this material for (UInt f = 0; f < nb_facet; ++f, ++sigma_lim_it) { UInt facet = f_filter(f); // skip facets where check shouldn't be realized if (!facets_check(facet)) continue; // compute the effective norm on each quadrature point of the facet for (UInt q = 0; q < nb_quad_facet; ++q) { UInt current_quad = facet * nb_quad_facet + q; const Vector<Real> & normal = normal_begin[current_quad]; const Vector<Real> & tangent = tangent_begin[current_quad]; const Matrix<Real> & facet_stress_it = facet_stress_begin[current_quad]; // compute average stress on the current quadrature point Matrix<Real> stress_1(facet_stress_it.storage(), spatial_dimension, spatial_dimension); Matrix<Real> stress_2(facet_stress_it.storage() + sp2, spatial_dimension, spatial_dimension); stress_tmp.copy(stress_1); stress_tmp += stress_2; stress_tmp /= 2.; Vector<Real> normal_traction_vec(normal_traction(q)); // compute normal and effective stress stress_check(q) = computeEffectiveNorm(stress_tmp, normal, tangent, normal_traction_vec); } // verify if the effective stress overcomes the threshold Real final_stress = stress_check.mean(); if (max_quad_stress_insertion) final_stress = *std::max_element( stress_check.storage(), stress_check.storage() + nb_quad_facet); if (final_stress > (*sigma_lim_it - tolerance)) { if (model->isExplicit()) { f_insertion(facet) = true; if (!check_only) { // store the new cohesive material parameters for each quadrature // point for (UInt q = 0; q < nb_quad_facet; ++q) { Real new_sigma = stress_check(q); Vector<Real> normal_traction_vec(normal_traction(q)); if (spatial_dimension != 3) normal_traction_vec *= -1.; new_sigmas.push_back(new_sigma); new_normal_traction.push_back(normal_traction_vec); Real new_delta; // set delta_c in function of G_c or a given delta_c value if (Math::are_float_equal(delta_c, 0.)) new_delta = 2 * G_c / new_sigma; else new_delta = (*sigma_lim_it) / new_sigma * delta_c; new_delta_c.push_back(new_delta); } } } else { Real ratio = final_stress / (*sigma_lim_it); if (ratio > max_ratio) { ++nn; max_ratio = ratio; index_f = f; index_filter = f_filter(f); } } } } /// Insertion of only 1 cohesive element in case of implicit approach. The /// one subjected to the highest stress. if (!model->isExplicit()) { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Array<Real> abs_max(comm.getNbProc()); abs_max(comm.whoAmI()) = max_ratio; comm.allGather(abs_max.storage(), 1); Array<Real>::scalar_iterator it = std::max_element(abs_max.begin(), abs_max.end()); Int pos = it - abs_max.begin(); if (pos != comm.whoAmI()) { AKANTU_DEBUG_OUT(); return; } if (nn) { f_insertion(index_filter) = true; if (!check_only) { // Array<Real>::iterator<Matrix<Real> > normal_traction_it = // normal_traction.begin_reinterpret(nb_quad_facet, // spatial_dimension, nb_facet); Array<Real>::const_iterator<Real> sigma_lim_it = sigma_lim.begin(); for (UInt q = 0; q < nb_quad_cohesive; ++q) { Real new_sigma = (sigma_lim_it[index_f]); Vector<Real> normal_traction_vec(spatial_dimension, 0.0); new_sigmas.push_back(new_sigma); new_normal_traction.push_back(normal_traction_vec); Real new_delta; // set delta_c in function of G_c or a given delta_c value if (!Math::are_float_equal(delta_c, 0.)) new_delta = delta_c; else new_delta = 2 * G_c / (new_sigma); new_delta_c.push_back(new_delta); } } } } // update material data for the new elements UInt old_nb_quad_points = sig_c_eff.getSize(); UInt new_nb_quad_points = new_sigmas.size(); sig_c_eff.resize(old_nb_quad_points + new_nb_quad_points); ins_stress.resize(old_nb_quad_points + new_nb_quad_points); trac_old.resize(old_nb_quad_points + new_nb_quad_points); del_c.resize(old_nb_quad_points + new_nb_quad_points); open_prec.resize(old_nb_quad_points + new_nb_quad_points); red_penalty.resize(old_nb_quad_points + new_nb_quad_points); for (UInt q = 0; q < new_nb_quad_points; ++q) { sig_c_eff(old_nb_quad_points + q) = new_sigmas[q]; del_c(old_nb_quad_points + q) = new_delta_c[q]; red_penalty(old_nb_quad_points + q) = false; for (UInt dim = 0; dim < spatial_dimension; ++dim) { ins_stress(old_nb_quad_points + q, dim) = new_normal_traction[q](dim); trac_old(old_nb_quad_points + q, dim) = new_normal_traction[q](dim); open_prec(old_nb_quad_points + q, dim) = 0.; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::computeTraction( const Array<Real> & normal, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array<Real>::vector_iterator traction_it = tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator opening_it = opening(el_type, ghost_type).begin(spatial_dimension); /// opening_prec is the opening of the previous step in the /// Newton-Raphson loop Array<Real>::vector_iterator opening_prec_it = opening_prec(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_traction_it = contact_tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_opening_it = contact_opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::const_vector_iterator normal_it = normal.begin(spatial_dimension); Array<Real>::vector_iterator traction_end = tractions(el_type, ghost_type).end(spatial_dimension); Array<Real>::scalar_iterator sigma_c_it = sigma_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_max_it = delta_max(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_max_prev_it = delta_max.previous(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_c_it = delta_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator damage_it = damage(el_type, ghost_type).begin(); Array<Real>::vector_iterator insertion_stress_it = insertion_stress(el_type, ghost_type).begin(spatial_dimension); Array<bool>::scalar_iterator reduction_penalty_it = reduction_penalty(el_type, ghost_type).begin(); Vector<Real> normal_opening(spatial_dimension); Vector<Real> tangential_opening(spatial_dimension); if (!this->model->isExplicit()) this->delta_max(el_type, ghost_type) .copy(this->delta_max.previous(el_type, ghost_type)); /// loop on each quadrature point for (; traction_it != traction_end; ++traction_it, ++opening_it, ++opening_prec_it, ++normal_it, ++sigma_c_it, ++delta_max_it, ++delta_c_it, ++damage_it, ++contact_traction_it, ++insertion_stress_it, ++contact_opening_it, ++delta_max_prev_it, ++reduction_penalty_it) { Real normal_opening_norm, tangential_opening_norm; bool penetration; Real current_penalty = 0.; this->computeTractionOnQuad( *traction_it, *delta_max_it, *delta_max_prev_it, *delta_c_it, *insertion_stress_it, *sigma_c_it, *opening_it, *opening_prec_it, *normal_it, normal_opening, tangential_opening, normal_opening_norm, tangential_opening_norm, *damage_it, penetration, *reduction_penalty_it, current_penalty, *contact_traction_it, *contact_opening_it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::checkDeltaMax( GhostType ghost_type) { AKANTU_DEBUG_IN(); /** * This function set a predefined value to the parameter * delta_max_prev of the elements that have been inserted in the * last loading step for which convergence has not been * reached. This is done before reducing the loading and re-doing * the step. Otherwise, the updating of delta_max_prev would be * done with reference to the non-convergent solution. In this * function also other variables related to the contact and * friction behavior are correctly set. */ Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); /** * the variable "recompute" is set to true to activate the * procedure that reduce the penalty parameter for * compression. This procedure is set true only during the phase of * load_reduction, that has to be set in the maiin file. The * penalty parameter will be reduced only for the elements having * reduction_penalty = true. */ recompute = true; for (; it != last_type; ++it) { Array<UInt> & elem_filter = element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element == 0) continue; ElementType el_type = *it; /// define iterators Array<Real>::scalar_iterator delta_max_it = delta_max(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_max_end = delta_max(el_type, ghost_type).end(); Array<Real>::scalar_iterator delta_max_prev_it = delta_max.previous(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_c_it = delta_c_eff(el_type, ghost_type).begin(); Array<Real>::vector_iterator opening_prec_it = opening_prec(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator opening_prec_prev_it = opening_prec.previous(el_type, ghost_type).begin(spatial_dimension); /// loop on each quadrature point for (; delta_max_it != delta_max_end; ++delta_max_it, ++delta_max_prev_it, ++delta_c_it, ++opening_prec_it, ++opening_prec_prev_it) { if (*delta_max_prev_it == 0) /// elements inserted in the last incremental step, that did /// not converge *delta_max_it = *delta_c_it / 1000; else /// elements introduced in previous incremental steps, for /// which a correct value of delta_max_prev already exists *delta_max_it = *delta_max_prev_it; /// in case convergence is not reached, set opening_prec to the /// value referred to the previous incremental step *opening_prec_it = *opening_prec_prev_it; } } } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::resetVariables( GhostType ghost_type) { AKANTU_DEBUG_IN(); /** * This function set the variables "recompute" and * "reduction_penalty" to false. It is called by solveStepCohesive * when convergence is reached. Such variables, in fact, have to be * false at the beginning of a new incremental step. */ Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); recompute = false; for (; it != last_type; ++it) { Array<UInt> & elem_filter = element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element == 0) continue; ElementType el_type = *it; Array<bool>::scalar_iterator reduction_penalty_it = reduction_penalty(el_type, ghost_type).begin(); Array<bool>::scalar_iterator reduction_penalty_end = reduction_penalty(el_type, ghost_type).end(); /// loop on each quadrature point for (; reduction_penalty_it != reduction_penalty_end; ++reduction_penalty_it) { *reduction_penalty_it = false; } } } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::computeTangentTraction( const ElementType & el_type, Array<Real> & tangent_matrix, const Array<Real> & normal, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array<Real>::matrix_iterator tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension); Array<Real>::const_vector_iterator normal_it = normal.begin(spatial_dimension); Array<Real>::vector_iterator opening_it = opening(el_type, ghost_type).begin(spatial_dimension); /// NB: delta_max_it points on delta_max_previous, i.e. the /// delta_max related to the solution of the previous incremental /// step Array<Real>::scalar_iterator delta_max_it = delta_max.previous(el_type, ghost_type).begin(); Array<Real>::scalar_iterator sigma_c_it = sigma_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_c_it = delta_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator damage_it = damage(el_type, ghost_type).begin(); Array<Real>::vector_iterator contact_opening_it = contact_opening(el_type, ghost_type).begin(spatial_dimension); Array<bool>::scalar_iterator reduction_penalty_it = reduction_penalty(el_type, ghost_type).begin(); Vector<Real> normal_opening(spatial_dimension); Vector<Real> tangential_opening(spatial_dimension); for (; tangent_it != tangent_end; ++tangent_it, ++normal_it, ++opening_it, ++delta_max_it, ++sigma_c_it, ++delta_c_it, ++damage_it, ++contact_opening_it, ++reduction_penalty_it) { Real normal_opening_norm, tangential_opening_norm; bool penetration; Real current_penalty = 0.; this->computeTangentTractionOnQuad( *tangent_it, *delta_max_it, *delta_c_it, *sigma_c_it, *opening_it, *normal_it, normal_opening, tangential_opening, normal_opening_norm, tangential_opening_norm, *damage_it, penetration, *reduction_penalty_it, current_penalty, *contact_opening_it); // check if the tangential stiffness matrix is symmetric // for (UInt h = 0; h < spatial_dimension; ++h){ // for (UInt l = h; l < spatial_dimension; ++l){ // if (l > h){ // Real k_ls = (*tangent_it)[spatial_dimension*h+l]; // Real k_us = (*tangent_it)[spatial_dimension*l+h]; // // std::cout << "k_ls = " << k_ls << std::endl; // // std::cout << "k_us = " << k_us << std::endl; // if (std::abs(k_ls) > 1e-13 && std::abs(k_us) > 1e-13){ // Real error = std::abs((k_ls - k_us) / k_us); // if (error > 1e-10){ // std::cout << "non symmetric cohesive matrix" << std::endl; // // std::cout << "error " << error << std::endl; // } // } // } // } // } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialCohesiveLinear); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.hh b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.hh index e9bfe93e2..012ba1084 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.hh +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.hh @@ -1,216 +1,216 @@ /** * @file material_cohesive_linear.hh * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Jan 14 2016 * * @brief Linear irreversible cohesive law of mixed mode loading with * random stress definition for extrinsic type * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_cohesive.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_COHESIVE_LINEAR_HH__ #define __AKANTU_MATERIAL_COHESIVE_LINEAR_HH__ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /** * Cohesive material linear damage for extrinsic case * * parameters in the material files : * - sigma_c : critical stress sigma_c (default: 0) * - beta : weighting parameter for sliding and normal opening (default: 0) * - G_cI : fracture energy for mode I (default: 0) * - G_cII : fracture energy for mode II (default: 0) * - penalty : stiffness in compression to prevent penetration */ template<UInt spatial_dimension> class MaterialCohesiveLinear : public MaterialCohesive { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialCohesiveLinear(SolidMechanicsModel & model, const ID & id = ""); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the material parameters virtual void initMaterial(); /// check stress for cohesive elements' insertion virtual void checkInsertion(bool check_only = false); /// compute effective stress norm for insertion check Real computeEffectiveNorm(const Matrix<Real> & stress, const Vector<Real> & normal, const Vector<Real> & tangent, Vector<Real> & normal_stress) const; protected: /// constitutive law virtual void computeTraction(const Array<Real> & normal, ElementType el_type, GhostType ghost_type = _not_ghost); /// check delta_max for cohesive elements in case of no convergence /// in the solveStep (only for extrinsic-implicit) virtual void checkDeltaMax(GhostType ghost_type = _not_ghost); /// reset variables when convergence is reached (only for /// extrinsic-implicit) void resetVariables(GhostType ghost_type = _not_ghost); /// compute tangent stiffness matrix virtual void computeTangentTraction(const ElementType & el_type, Array<Real> & tangent_matrix, const Array<Real> & normal, GhostType ghost_type); /** * Scale insertion traction sigma_c according to the volume of the * two elements surrounding a facet * * see the article: F. Zhou and J. F. Molinari "Dynamic crack * propagation with cohesive elements: a methodology to address mesh * dependency" International Journal for Numerical Methods in * Engineering (2004) */ void scaleInsertionTraction(); /// compute the traction for a given quadrature point inline void computeTractionOnQuad(Vector<Real> & traction, Real & delta_max, const Real & delta_max_prev, const Real & delta_c, const Vector<Real> & insertion_stress, const Real & sigma_c, Vector<Real> & opening, Vector<Real> & opening_prec, const Vector<Real> & normal, Vector<Real> & normal_opening, Vector<Real> & tangential_opening, Real & normal_opening_norm, Real & tangential_opening_norm, Real & damage, bool & penetration, bool & reduction_penalty, Real & current_penalty, Vector<Real> & contact_traction, Vector<Real> & contact_opening); inline void computeTangentTractionOnQuad(Matrix<Real> & tangent, Real & delta_max, const Real & delta_c, const Real & sigma_c, Vector<Real> & opening, const Vector<Real> & normal, Vector<Real> & normal_opening, Vector<Real> & tangential_opening, Real & normal_opening_norm, Real & tangential_opening_norm, Real & damage, bool & penetration, bool & reduction_penalty, Real & current_penalty, Vector<Real> & contact_opening); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get sigma_c_eff AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(InsertionTraction, sigma_c_eff, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// beta parameter Real beta; /// beta square inverse to compute effective norm Real beta2_inv; /// mode I fracture energy Real G_c; /// kappa parameter Real kappa; /// constitutive law scalar to compute delta Real beta2_kappa2; /// constitutive law scalar to compute traction Real beta2_kappa; /// penalty coefficient Real penalty; /// reference volume used to scale sigma_c Real volume_s; /// weibull exponent used to scale sigma_c Real m_s; /// variable defining if we are recomputing the last loading step /// after load_reduction bool recompute; /// critical effective stress RandomInternalField<Real, CohesiveInternalField> sigma_c_eff; /// effective critical displacement (each element can have a /// different value) CohesiveInternalField<Real> delta_c_eff; /// stress at insertion CohesiveInternalField<Real> insertion_stress; /// delta of the previous step CohesiveInternalField<Real> opening_prec; /** * variable that defines if the penalty parameter for compression * has to be decreased for problems of convergence in the solution * loops */ CohesiveInternalField<bool> reduction_penalty; /// variable saying if there should be penalty contact also after /// breaking the cohesive elements bool contact_after_breaking; /// insertion of cohesive element when stress is high enough just on /// one quadrature point bool max_quad_stress_insertion; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #include "material_cohesive_linear_inline_impl.cc" #endif /* __AKANTU_MATERIAL_COHESIVE_LINEAR_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.cc index d467c7b81..27b8ac4b5 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.cc @@ -1,296 +1,296 @@ /** * @file material_cohesive_linear_fatigue.cc * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Feb 20 2015 * @date last modification: Tue Jan 12 2016 * * @brief See material_cohesive_linear_fatigue.hh for information * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_cohesive_linear_fatigue.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialCohesiveLinearFatigue<spatial_dimension> ::MaterialCohesiveLinearFatigue(SolidMechanicsModel & model, const ID & id) : MaterialCohesiveLinear<spatial_dimension>(model, id), delta_prec("delta_prec", *this), K_plus("K_plus", *this), K_minus("K_minus", *this), T_1d("T_1d", *this), switches("switches", *this), delta_dot_prec("delta_dot_prec", *this), normal_regime("normal_regime", *this) { this->registerParam("delta_f", delta_f, Real(-1.) , _pat_parsable | _pat_readable, "delta_f"); this->registerParam("progressive_delta_f", progressive_delta_f, false, _pat_parsable | _pat_readable, "Whether or not delta_f is equal to delta_max"); this->registerParam("count_switches", count_switches, false, _pat_parsable | _pat_readable, "Count the opening/closing switches per element"); this->registerParam("fatigue_ratio", fatigue_ratio, Real(1.), _pat_parsable | _pat_readable, "What portion of the cohesive law is subjected to fatigue"); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinearFatigue<spatial_dimension>::initMaterial() { MaterialCohesiveLinear<spatial_dimension>::initMaterial(); // check that delta_f has a proper value or assign a defaul value if (delta_f < 0) delta_f = this->delta_c_eff; else if (delta_f < this->delta_c_eff) AKANTU_DEBUG_ERROR("Delta_f must be greater or equal to delta_c"); delta_prec.initialize(1); K_plus.initialize(1); K_minus.initialize(1); T_1d.initialize(1); normal_regime.initialize(1); if (count_switches) { switches.initialize(1); delta_dot_prec.initialize(1); } } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinearFatigue<spatial_dimension> ::computeTraction(const Array<Real> & normal, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array<Real>::vector_iterator traction_it = this->tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_traction_it = this->contact_tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_opening_it = this->contact_opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::const_vector_iterator normal_it = normal.begin(spatial_dimension); Array<Real>::vector_iterator traction_end = this->tractions(el_type, ghost_type).end(spatial_dimension); const Array<Real> & sigma_c_array = this->sigma_c_eff(el_type, ghost_type); Array<Real> & delta_max_array = this->delta_max(el_type, ghost_type); const Array<Real> & delta_c_array = this->delta_c_eff(el_type, ghost_type); Array<Real> & damage_array = this->damage(el_type, ghost_type); Array<Real>::vector_iterator insertion_stress_it = this->insertion_stress(el_type, ghost_type).begin(spatial_dimension); Array<Real> & delta_prec_array = delta_prec(el_type, ghost_type); Array<Real> & K_plus_array = K_plus(el_type, ghost_type); Array<Real> & K_minus_array = K_minus(el_type, ghost_type); Array<Real> & T_1d_array = T_1d(el_type, ghost_type); Array<bool> & normal_regime_array = normal_regime(el_type, ghost_type); Array<UInt> * switches_array = NULL; Array<Real> * delta_dot_prec_array = NULL; if (count_switches) { switches_array = &switches(el_type, ghost_type); delta_dot_prec_array = &delta_dot_prec(el_type, ghost_type); } Real * memory_space = new Real[2*spatial_dimension]; Vector<Real> normal_opening(memory_space, spatial_dimension); Vector<Real> tangential_opening(memory_space + spatial_dimension, spatial_dimension); Real tolerance = Math::getTolerance(); /// loop on each quadrature point for (UInt q = 0; traction_it != traction_end; ++traction_it, ++opening_it, ++normal_it, ++contact_traction_it, ++insertion_stress_it, ++contact_opening_it, ++q) { /// compute normal and tangential opening vectors Real normal_opening_norm = opening_it->dot(*normal_it); normal_opening = (*normal_it); normal_opening *= normal_opening_norm; tangential_opening = *opening_it; tangential_opening -= normal_opening; Real tangential_opening_norm = tangential_opening.norm(); /** * compute effective opening displacement * @f$ \delta = \sqrt{ * \frac{\beta^2}{\kappa^2} \Delta_t^2 + \Delta_n^2 } @f$ */ Real delta = tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2; bool penetration = normal_opening_norm < -tolerance; if (this->contact_after_breaking == false && Math::are_float_equal(damage_array(q), 1.)) penetration = false; if (penetration) { /// use penalty coefficient in case of penetration *contact_traction_it = normal_opening; *contact_traction_it *= this->penalty; *contact_opening_it = normal_opening; /// don't consider penetration contribution for delta *opening_it = tangential_opening; normal_opening.clear(); } else { delta += normal_opening_norm * normal_opening_norm; contact_traction_it->clear(); contact_opening_it->clear(); } delta = std::sqrt(delta); /** * Compute traction @f$ \mathbf{T} = \left( * \frac{\beta^2}{\kappa} \Delta_t \mathbf{t} + \Delta_n * \mathbf{n} \right) \frac{\sigma_c}{\delta} \left( 1- * \frac{\delta}{\delta_c} \right)@f$ */ // update maximum displacement and damage delta_max_array(q) = std::max(delta, delta_max_array(q)); damage_array(q) = std::min(delta_max_array(q) / delta_c_array(q), Real(1.)); Real delta_dot = delta - delta_prec_array(q); // count switches if asked if (count_switches) { if ( (delta_dot > 0. && (*delta_dot_prec_array)(q) <= 0.) || (delta_dot < 0. && (*delta_dot_prec_array)(q) >= 0.) ) ++((*switches_array)(q)); (*delta_dot_prec_array)(q) = delta_dot; } // set delta_f equal to delta_max if desired if (progressive_delta_f) delta_f = delta_max_array(q); // broken element case if (Math::are_float_equal(damage_array(q), 1.)) traction_it->clear(); // just inserted element case else if (Math::are_float_equal(damage_array(q), 0.)) { if (penetration) traction_it->clear(); else *traction_it = *insertion_stress_it; // initialize the 1d traction to sigma_c T_1d_array(q) = sigma_c_array(q); } // normal case else { // if element is closed then there are zero tractions if (delta <= tolerance) traction_it->clear(); // otherwise compute new tractions if the new delta is different // than the previous one else if (std::abs(delta_dot) > tolerance) { // loading case if (delta_dot > 0.) { if (!normal_regime_array(q)) { // equation (4) of the article K_plus_array(q) *= 1. - delta_dot / delta_f; // equivalent to equation (2) of the article T_1d_array(q) += K_plus_array(q) * delta_dot; // in case of reloading, traction must not exceed that of the // envelop of the cohesive law Real max_traction = sigma_c_array(q) * (1 - delta / delta_c_array(q)); bool max_traction_exceeded = T_1d_array(q) > max_traction; if (max_traction_exceeded) T_1d_array(q) = max_traction; // switch to standard linear cohesive law if (delta_max_array(q) > fatigue_ratio * delta_c_array(q)) { // reset delta_max to avoid big jumps in the traction delta_max_array(q) = sigma_c_array(q) / (T_1d_array(q) / delta + sigma_c_array(q) / delta_c_array(q)); damage_array(q) = std::min(delta_max_array(q) / delta_c_array(q), Real(1.)); K_minus_array(q) = sigma_c_array(q) / delta_max_array(q) * (1. - damage_array(q)); normal_regime_array(q) = true; } else { // equation (3) of the article K_minus_array(q) = T_1d_array(q) / delta; // if the traction is following the cohesive envelop, then // K_plus has to be reset if (max_traction_exceeded) K_plus_array(q) = K_minus_array(q); } } else { // compute stiffness according to the standard law K_minus_array(q) = sigma_c_array(q) / delta_max_array(q) * (1. - damage_array(q)); } } // unloading case else if (!normal_regime_array(q)) { // equation (4) of the article K_plus_array(q) += (K_plus_array(q) - K_minus_array(q)) * delta_dot / delta_f; // equivalent to equation (2) of the article T_1d_array(q) = K_minus_array(q) * delta; } // applying the actual stiffness *traction_it = tangential_opening; *traction_it *= this->beta2_kappa; *traction_it += normal_opening; *traction_it *= K_minus_array(q); } } // update precendent delta delta_prec_array(q) = delta; } delete [] memory_space; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialCohesiveLinearFatigue); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.hh b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.hh index dedda9b19..b90cc640c 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.hh +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.hh @@ -1,136 +1,136 @@ /** * @file material_cohesive_linear_fatigue.hh * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Jun 25 2015 * * @brief Linear irreversible cohesive law with dissipative * unloading-reloading cycles * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_cohesive_linear.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_COHESIVE_LINEAR_FATIGUE_HH__ #define __AKANTU_MATERIAL_COHESIVE_LINEAR_FATIGUE_HH__ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /** * Linear irreversible cohesive law with dissipative * unloading-reloading cycles * * This law uses two different stiffnesses during unloading and * reloading. The implementation is based on the article entitled "A * cohesive model for fatigue crack growth" by Nguyen, Repetto, Ortiz * and Radovitzky (2001). This law is identical to the * MaterialCohesiveLinear one except for the unloading-reloading * phase. * * input parameter: * * - delta_f : it must be greater than delta_c and it is inversely * proportional to the dissipation in the unloading-reloading * cycles (default: delta_c) */ template <UInt spatial_dimension> class MaterialCohesiveLinearFatigue : public MaterialCohesiveLinear<spatial_dimension> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialCohesiveLinearFatigue(SolidMechanicsModel & model, const ID & id = ""); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the material parameters virtual void initMaterial(); protected: /// constitutive law virtual void computeTraction(const Array<Real> & normal, ElementType el_type, GhostType ghost_type = _not_ghost); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the switches AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Switches, switches, UInt); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// delta_f parameter Real delta_f; /// variable saying if delta_f is equal to delta_max for each /// element when the traction is computed bool progressive_delta_f; /// count the opening/closing switches per element bool count_switches; /// delta of the previous step CohesiveInternalField<Real> delta_prec; /// stiffness for reloading CohesiveInternalField<Real> K_plus; /// stiffness for unloading CohesiveInternalField<Real> K_minus; /// 1D traction in the cohesive law CohesiveInternalField<Real> T_1d; /// Number of opening/closing switches CohesiveInternalField<UInt> switches; /// delta increment of the previous time step CohesiveInternalField<Real> delta_dot_prec; /// has the element passed to normal regime (not in fatigue anymore) CohesiveInternalField<bool> normal_regime; /// ratio indicating until what point fatigue is applied in the cohesive law Real fatigue_ratio; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_COHESIVE_LINEAR_FATIGUE_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.cc index 94e88ed3a..4892833f3 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.cc @@ -1,401 +1,401 @@ /** * @file material_cohesive_linear_friction.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date creation: Tue Jan 12 2016 * @date last modification: Thu Jan 14 2016 * * @brief Linear irreversible cohesive law of mixed mode loading with * random stress definition for extrinsic type * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_cohesive_linear_friction.hh" #include "solid_mechanics_model_cohesive.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialCohesiveLinearFriction<spatial_dimension>::MaterialCohesiveLinearFriction(SolidMechanicsModel & model, const ID & id) : MaterialParent(model,id), residual_sliding("residual_sliding", *this), friction_force("friction_force", *this) { AKANTU_DEBUG_IN(); this->registerParam("mu", mu_max, Real(0.), _pat_parsable | _pat_readable, "Maximum value of the friction coefficient"); this->registerParam("penalty_for_friction", friction_penalty, Real(0.), _pat_parsable | _pat_readable, "Penalty parameter for the friction behavior"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinearFriction<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialParent::initMaterial(); friction_force.initialize(spatial_dimension); residual_sliding.initialize(1); residual_sliding.initializeHistory(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinearFriction<spatial_dimension>::computeTraction(__attribute__((unused)) const Array<Real> & normal, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); residual_sliding.resize(); friction_force.resize(); /// define iterators Array<Real>::vector_iterator traction_it = this->tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator traction_end = this->tractions(el_type, ghost_type).end(spatial_dimension); Array<Real>::vector_iterator opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension); /// opening_prec is the opening at the end of the previous step in /// the Newton-Raphson loop Array<Real>::vector_iterator opening_prec_it = this->opening_prec(el_type, ghost_type).begin(spatial_dimension); /// opening_prec_prev is the opening (opening + penetration) /// referred to the convergence of the previous incremental step Array<Real>::vector_iterator opening_prec_prev_it = this->opening_prec.previous(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_traction_it = this->contact_tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_opening_it = this->contact_opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::const_iterator< Vector<Real> > normal_it = this->normal.begin(spatial_dimension); Array<Real>::iterator<Real>sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin(); Array<Real>::iterator<Real>delta_max_it = this->delta_max(el_type, ghost_type).begin(); Array<Real>::iterator<Real>delta_max_prev_it = this->delta_max.previous(el_type, ghost_type).begin(); Array<Real>::iterator<Real>delta_c_it = this->delta_c_eff(el_type, ghost_type).begin(); Array<Real>::iterator<Real>damage_it = this->damage(el_type, ghost_type).begin(); Array<Real>::vector_iterator insertion_stress_it = this->insertion_stress(el_type, ghost_type).begin(spatial_dimension); Array<Real>::iterator<Real>res_sliding_it = this->residual_sliding(el_type, ghost_type).begin(); Array<Real>::iterator<Real>res_sliding_prev_it = this->residual_sliding.previous(el_type, ghost_type).begin(); Array<Real>::vector_iterator friction_force_it = this->friction_force(el_type, ghost_type).begin(spatial_dimension); Array<bool>::iterator<bool> reduction_penalty_it = this->reduction_penalty(el_type, ghost_type).begin(); Vector<Real> normal_opening(spatial_dimension); Vector<Real> tangential_opening(spatial_dimension); if (! this->model->isExplicit()) this->delta_max(el_type, ghost_type).copy(this->delta_max.previous(el_type, ghost_type)); /// loop on each quadrature point for (; traction_it != traction_end; ++traction_it, ++opening_it, ++opening_prec_prev_it, ++opening_prec_it, ++normal_it, ++sigma_c_it, ++delta_max_it, ++delta_c_it, ++damage_it, ++contact_traction_it, ++insertion_stress_it, ++contact_opening_it, ++delta_max_prev_it, ++res_sliding_it, ++res_sliding_prev_it, ++friction_force_it, ++reduction_penalty_it) { Real normal_opening_norm, tangential_opening_norm; bool penetration; Real current_penalty = 0.; this->computeTractionOnQuad(*traction_it, *delta_max_it, *delta_max_prev_it, *delta_c_it, *insertion_stress_it, *sigma_c_it, *opening_it, *opening_prec_it, *normal_it, normal_opening, tangential_opening, normal_opening_norm, tangential_opening_norm, *damage_it, penetration, *reduction_penalty_it, current_penalty, *contact_traction_it, *contact_opening_it); if (penetration) { /// the friction coefficient mu increases with the damage. It /// equals the maximum value when damage = 1. // Real damage = std::min(*delta_max_prev_it / *delta_c_it, Real(1.)); Real mu = mu_max; // * damage; /// the definition of tau_max refers to the opening /// (penetration) of the previous incremental step Real normal_opening_prev_norm = std::min(opening_prec_prev_it->dot(*normal_it), Real(0.)); // Vector<Real> normal_opening_prev = (*normal_it); // normal_opening_prev *= normal_opening_prev_norm; Real tau_max = mu * current_penalty * (std::abs(normal_opening_prev_norm)); Real delta_sliding_norm = std::abs(tangential_opening_norm - *res_sliding_prev_it); /// tau is the norm of the friction force, acting tangentially to the surface Real tau = std::min(friction_penalty * delta_sliding_norm, tau_max); if ((tangential_opening_norm - *res_sliding_prev_it) < 0.0) tau = -tau; /// from tau get the x and y components of friction, to be added in the force vector Vector<Real> tangent_unit_vector(spatial_dimension); tangent_unit_vector = tangential_opening / tangential_opening_norm; *friction_force_it = tau * tangent_unit_vector; /// update residual_sliding *res_sliding_it = tangential_opening_norm - (std::abs(tau) / friction_penalty); } else { friction_force_it->clear(); } *traction_it += *friction_force_it; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinearFriction<spatial_dimension>::checkDeltaMax(GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialParent::checkDeltaMax(); Mesh & mesh = this->fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); for(; it != last_type; ++it) { Array<UInt> & elem_filter = this->element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element == 0) continue; ElementType el_type = *it; /// define iterators Array<Real>::iterator<Real>delta_max_it = this->delta_max(el_type, ghost_type).begin(); Array<Real>::iterator<Real>delta_max_end = this->delta_max(el_type, ghost_type).end(); Array<Real>::iterator<Real>res_sliding_it = this->residual_sliding(el_type, ghost_type).begin(); Array<Real>::iterator<Real>res_sliding_prev_it = this->residual_sliding.previous(el_type, ghost_type).begin(); /// loop on each quadrature point for (; delta_max_it != delta_max_end; ++delta_max_it, ++res_sliding_it, ++res_sliding_prev_it) { /** * in case convergence is not reached, set "residual_sliding" * for the friction behaviour to the value referred to the * previous incremental step */ *res_sliding_it = *res_sliding_prev_it; } } } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinearFriction<spatial_dimension>::computeTangentTraction(const ElementType & el_type, Array<Real> & tangent_matrix, __attribute__((unused)) const Array<Real> & normal, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array<Real>::matrix_iterator tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension); Array<Real>::const_vector_iterator normal_it = this->normal.begin(spatial_dimension); Array<Real>::vector_iterator opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator opening_prec_prev_it = this->opening_prec.previous(el_type, ghost_type).begin(spatial_dimension); /** * NB: delta_max_it points on delta_max_previous, i.e. the * delta_max related to the solution of the previous incremental * step */ Array<Real>::iterator<Real>delta_max_it = this->delta_max.previous(el_type, ghost_type).begin(); Array<Real>::iterator<Real>sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin(); Array<Real>::iterator<Real>delta_c_it = this->delta_c_eff(el_type, ghost_type).begin(); Array<Real>::iterator<Real>damage_it = this->damage(el_type, ghost_type).begin(); Array<Real>::iterator< Vector<Real> > contact_opening_it = this->contact_opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::iterator<Real>res_sliding_prev_it = this->residual_sliding.previous(el_type, ghost_type).begin(); Array<bool>::iterator<bool> reduction_penalty_it = this->reduction_penalty(el_type, ghost_type).begin(); Vector<Real> normal_opening(spatial_dimension); Vector<Real> tangential_opening(spatial_dimension); for (; tangent_it != tangent_end; ++tangent_it, ++normal_it, ++opening_it, ++opening_prec_prev_it, ++delta_max_it, ++sigma_c_it, ++delta_c_it, ++damage_it, ++contact_opening_it, ++res_sliding_prev_it, ++reduction_penalty_it) { Real normal_opening_norm, tangential_opening_norm; bool penetration; Real current_penalty = 0.; this->computeTangentTractionOnQuad(*tangent_it, *delta_max_it, *delta_c_it, *sigma_c_it, *opening_it, *normal_it, normal_opening, tangential_opening, normal_opening_norm, tangential_opening_norm, *damage_it, penetration, *reduction_penalty_it, current_penalty, *contact_opening_it); if (penetration) { // Real damage = std::min(*delta_max_it / *delta_c_it, Real(1.)); Real mu = mu_max; // * damage; Real normal_opening_prev_norm = std::min(opening_prec_prev_it->dot(*normal_it), Real(0.)); // Vector<Real> normal_opening_prev = (*normal_it); // normal_opening_prev *= normal_opening_prev_norm; Real tau_max = mu * current_penalty * (std::abs(normal_opening_prev_norm)); Real delta_sliding_norm = std::abs(tangential_opening_norm - *res_sliding_prev_it); // tau is the norm of the friction force, acting tangentially to the surface Real tau = std::min(friction_penalty * delta_sliding_norm, tau_max); if (tau < tau_max && tau_max > Math::getTolerance()){ Matrix<Real> I(spatial_dimension, spatial_dimension); I.eye(1.); Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension); n_outer_n.outerProduct(*normal_it, *normal_it); Matrix<Real> nn(n_outer_n); I -= nn; *tangent_it += I * friction_penalty; } } // check if the tangential stiffness matrix is symmetric // for (UInt h = 0; h < spatial_dimension; ++h){ // for (UInt l = h; l < spatial_dimension; ++l){ // if (l > h){ // Real k_ls = (*tangent_it)[spatial_dimension*h+l]; // Real k_us = (*tangent_it)[spatial_dimension*l+h]; // // std::cout << "k_ls = " << k_ls << std::endl; // // std::cout << "k_us = " << k_us << std::endl; // if (std::abs(k_ls) > 1e-13 && std::abs(k_us) > 1e-13){ // Real error = std::abs((k_ls - k_us) / k_us); // if (error > 1e-10){ // std::cout << "non symmetric cohesive matrix" << std::endl; // // std::cout << "error " << error << std::endl; // } // } // } // } // } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialCohesiveLinearFriction); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.hh b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.hh index 841913221..687d72b89 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.hh +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.hh @@ -1,112 +1,112 @@ /** * @file material_cohesive_linear_friction.hh * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Jan 12 2016 * * @brief Linear irreversible cohesive law of mixed mode loading with * random stress definition for extrinsic type * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_cohesive_linear.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_HH__ #define __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_HH__ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /** * Cohesive material linear with friction force * * parameters in the material files : * - mu : friction coefficient * - penalty_for_friction : Penalty parameter for the friction behavior */ template<UInt spatial_dimension> class MaterialCohesiveLinearFriction : public MaterialCohesiveLinear<spatial_dimension> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ typedef MaterialCohesiveLinear<spatial_dimension> MaterialParent; public: MaterialCohesiveLinearFriction(SolidMechanicsModel & model, const ID & id = ""); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the material parameters virtual void initMaterial(); protected: /// constitutive law virtual void computeTraction(const Array<Real> & normal, ElementType el_type, GhostType ghost_type = _not_ghost); /// check delta_max for cohesive elements in case of no convergence /// in the solveStep (only for extrinsic-implicit) virtual void checkDeltaMax(GhostType ghost_type = _not_ghost); /// compute tangent stiffness matrix virtual void computeTangentTraction(const ElementType & el_type, Array<Real> & tangent_matrix, const Array<Real> & normal, GhostType ghost_type); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// maximum value of the friction coefficient Real mu_max; /// penalty parameter for the friction law Real friction_penalty; /// history parameter for the friction law CohesiveInternalField<Real> residual_sliding; /// friction force CohesiveInternalField<Real> friction_force; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_inline_impl.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_inline_impl.cc index 0b1847bc2..3ad8dc6d9 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_inline_impl.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_inline_impl.cc @@ -1,315 +1,315 @@ /** * @file material_cohesive_linear_inline_impl.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Apr 22 2015 * @date last modification: Thu Jan 14 2016 * * @brief Inline functions of the MaterialCohesiveLinear * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_COHESIVE_LINEAR_INLINE_IMPL_CC__ #define __AKANTU_MATERIAL_COHESIVE_LINEAR_INLINE_IMPL_CC__ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt dim> inline Real MaterialCohesiveLinear<dim>::computeEffectiveNorm(const Matrix<Real> & stress, const Vector<Real> & normal, const Vector<Real> & tangent, Vector<Real> & normal_traction) const { normal_traction.mul<false>(stress, normal); Real normal_contrib = normal_traction.dot(normal); /// in 3D tangential components must be summed Real tangent_contrib = 0; if (dim == 2) { Real tangent_contrib_tmp = normal_traction.dot(tangent); tangent_contrib += tangent_contrib_tmp * tangent_contrib_tmp; } else if (dim == 3) { for (UInt s = 0; s < dim - 1; ++s) { const Vector<Real> tangent_v(tangent.storage() + s * dim, dim); Real tangent_contrib_tmp = normal_traction.dot(tangent_v); tangent_contrib += tangent_contrib_tmp * tangent_contrib_tmp; } } tangent_contrib = std::sqrt(tangent_contrib); normal_contrib = std::max(Real(0.), normal_contrib); return std::sqrt(normal_contrib * normal_contrib + tangent_contrib * tangent_contrib * beta2_inv); } /* -------------------------------------------------------------------------- */ template<UInt dim> inline void MaterialCohesiveLinear<dim>::computeTractionOnQuad( Vector<Real> & traction, Real & delta_max, __attribute__((unused)) const Real & delta_max_prev, const Real & delta_c, const Vector<Real> & insertion_stress, const Real & sigma_c, Vector<Real> & opening, Vector<Real> & opening_prec, const Vector<Real> & normal, Vector<Real> & normal_opening, Vector<Real> & tangential_opening, Real & normal_opening_norm, Real & tangential_opening_norm, Real & damage, bool & penetration, bool & reduction_penalty, Real & current_penalty, Vector<Real> & contact_traction, Vector<Real> & contact_opening) { /// compute normal and tangential opening vectors normal_opening_norm = opening.dot(normal); normal_opening = normal; normal_opening *= normal_opening_norm; tangential_opening = opening; tangential_opening -= normal_opening; tangential_opening_norm = tangential_opening.norm(); /** * compute effective opening displacement * @f$ \delta = \sqrt{ * \frac{\beta^2}{\kappa^2} \Delta_t^2 + \Delta_n^2 } @f$ */ Real delta = tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2; penetration = normal_opening_norm < 0.0; if (this->contact_after_breaking == false && Math::are_float_equal(damage, 1.)) penetration = false; /** * if during the convergence loop a cohesive element continues to * jumps from penetration to opening, and convergence is not * reached, its penalty parameter will be reduced in the * recomputation of the same incremental step. recompute is set * equal to true when convergence is not reached in the * solveStepCohesive function and the execution of the program * goes back to the main file where the variable load_reduction * is set equal to true. */ Real normal_opening_prec_norm = opening_prec.dot(normal); opening_prec = opening; if (!this->model->isExplicit() && !this->recompute) if ((normal_opening_prec_norm * normal_opening_norm) < 0.0) { reduction_penalty = true; } if (penetration) { if (this->recompute && reduction_penalty){ /// the penalty parameter is locally reduced current_penalty = this->penalty / 100.; } else current_penalty = this->penalty; /// use penalty coefficient in case of penetration contact_traction = normal_opening; contact_traction *= current_penalty; contact_opening = normal_opening; /// don't consider penetration contribution for delta opening = tangential_opening; normal_opening.clear(); } else { delta += normal_opening_norm * normal_opening_norm; contact_traction.clear(); contact_opening.clear(); } delta = std::sqrt(delta); /// update maximum displacement and damage delta_max = std::max(delta_max, delta); damage = std::min(delta_max / delta_c, Real(1.)); /** * Compute traction @f$ \mathbf{T} = \left( * \frac{\beta^2}{\kappa} \Delta_t \mathbf{t} + \Delta_n * \mathbf{n} \right) \frac{\sigma_c}{\delta} \left( 1- * \frac{\delta}{\delta_c} \right)@f$ */ if (Math::are_float_equal(damage, 1.)) traction.clear(); else if (Math::are_float_equal(damage, 0.)) { if (penetration) traction.clear(); else traction = insertion_stress; } else { traction = tangential_opening; traction *= this->beta2_kappa; traction += normal_opening; AKANTU_DEBUG_ASSERT(delta_max != 0., "Division by zero, tolerance might be too low"); traction *= sigma_c / delta_max * (1. - damage); } } /* -------------------------------------------------------------------------- */ template<UInt dim> inline void MaterialCohesiveLinear<dim>::computeTangentTractionOnQuad( Matrix<Real> & tangent, Real & delta_max, const Real & delta_c, const Real & sigma_c, Vector<Real> & opening, const Vector<Real> & normal, Vector<Real> & normal_opening, Vector<Real> & tangential_opening, Real & normal_opening_norm, Real & tangential_opening_norm, Real & damage, bool & penetration, bool & reduction_penalty, Real & current_penalty, Vector<Real> & contact_opening) { /** * During the update of the residual the interpenetrations are * stored in the array "contact_opening", therefore, in the case * of penetration, in the array "opening" there are only the * tangential components. */ opening += contact_opening; /// compute normal and tangential opening vectors normal_opening_norm = opening.dot(normal); normal_opening = normal; normal_opening *= normal_opening_norm; tangential_opening = opening; tangential_opening -= normal_opening; tangential_opening_norm = tangential_opening.norm(); Real delta = tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2; penetration = normal_opening_norm < 0.0; if (this->contact_after_breaking == false && Math::are_float_equal(damage, 1.)) penetration = false; Real derivative = 0; // derivative = d(t/delta)/ddelta Real t = 0; Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension); n_outer_n.outerProduct(normal, normal); if (penetration){ if (this->recompute && reduction_penalty) current_penalty = this->penalty / 100.; else current_penalty = this->penalty; /// stiffness in compression given by the penalty parameter tangent += n_outer_n; tangent *= current_penalty; opening = tangential_opening; normal_opening_norm = opening.dot(normal); normal_opening = normal; normal_opening *= normal_opening_norm; } else{ delta += normal_opening_norm * normal_opening_norm; } delta = std::sqrt(delta); /** * Delta has to be different from 0 to have finite values of * tangential stiffness. At the element insertion, delta = * 0. Therefore, a fictictious value is defined, for the * evaluation of the first value of K. */ if (delta < Math::getTolerance()) delta = delta_c / 1000.; if (delta >= delta_max){ if (delta <= delta_c){ derivative = -sigma_c / (delta * delta); t = sigma_c * (1 - delta / delta_c); } else { derivative = 0.; t = 0.; } } else if (delta < delta_max){ Real tmax = sigma_c * (1 - delta_max / delta_c); t = tmax / delta_max * delta; } /// computation of the derivative of the constitutive law (dT/ddelta) Matrix<Real> I(spatial_dimension, spatial_dimension); I.eye(this->beta2_kappa); Matrix<Real> nn(n_outer_n); nn *= (1. - this->beta2_kappa); nn += I; nn *= t/delta; Vector<Real> t_tilde(normal_opening); t_tilde *= (1. - this->beta2_kappa2); Vector<Real> mm(opening); mm *= this->beta2_kappa2; t_tilde += mm; Vector<Real> t_hat(normal_opening); t_hat += this->beta2_kappa * tangential_opening; Matrix<Real> prov(spatial_dimension, spatial_dimension); prov.outerProduct(t_hat, t_tilde); prov *= derivative/delta; prov += nn; Matrix<Real> prov_t = prov.transpose(); tangent += prov_t; } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu /* -------------------------------------------------------------------------- */ #endif //__AKANTU_MATERIAL_COHESIVE_LINEAR_INLINE_IMPL_CC__ diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.cc index a8641f161..053303060 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.cc @@ -1,599 +1,599 @@ /** * @file material_cohesive_linear_uncoupled.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date creation: Wed Feb 22 2012 * @date last modification: Thu Jan 14 2016 * * @brief Linear irreversible cohesive law of mixed mode loading with * random stress definition for extrinsic type * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <algorithm> #include <numeric> /* -------------------------------------------------------------------------- */ #include "material_cohesive_linear_uncoupled.hh" #include "solid_mechanics_model_cohesive.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialCohesiveLinearUncoupled<spatial_dimension> ::MaterialCohesiveLinearUncoupled(SolidMechanicsModel & model, const ID & id) : MaterialCohesiveLinear<spatial_dimension>(model,id), delta_n_max("delta_n_max", *this), delta_t_max("delta_t_max", *this), damage_n("damage_n", *this), damage_t("damage_t", *this){ AKANTU_DEBUG_IN(); this->registerParam("roughness", R, Real(1.), _pat_parsable | _pat_readable, "Roughness to define coupling between mode II and mode I"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinearUncoupled<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialCohesiveLinear<spatial_dimension>::initMaterial(); delta_n_max.initialize(1); delta_t_max.initialize(1); damage_n.initialize(1); damage_t.initialize(1); delta_n_max.initializeHistory(); delta_t_max.initializeHistory(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinearUncoupled<spatial_dimension>::computeTraction(const Array<Real> & normal, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); delta_n_max.resize(); delta_t_max.resize(); damage_n.resize(); damage_t.resize(); /// define iterators Array<Real>::vector_iterator traction_it = this->tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator traction_end = this->tractions(el_type, ghost_type).end(spatial_dimension); Array<Real>::vector_iterator opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension); /// opening_prec is the opening of the previous step in the /// Newton-Raphson loop Array<Real>::vector_iterator opening_prec_it = this->opening_prec(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_traction_it = this->contact_tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_opening_it = this->contact_opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::const_vector_iterator normal_it = this->normal.begin(spatial_dimension); Array<Real>::scalar_iterator sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_n_max_it = delta_n_max(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_t_max_it = delta_t_max(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_c_it = this->delta_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator damage_n_it = damage_n(el_type, ghost_type).begin(); Array<Real>::scalar_iterator damage_t_it = damage_t(el_type, ghost_type).begin(); Array<Real>::vector_iterator insertion_stress_it = this->insertion_stress(el_type, ghost_type).begin(spatial_dimension); Array<bool>::scalar_iterator reduction_penalty_it = this->reduction_penalty(el_type, ghost_type).begin(); Vector<Real> normal_opening(spatial_dimension); Vector<Real> tangential_opening(spatial_dimension); if (!this->model->isExplicit()){ this->delta_n_max(el_type, ghost_type).copy(this->delta_n_max.previous(el_type, ghost_type)); this->delta_t_max(el_type, ghost_type).copy(this->delta_t_max.previous(el_type, ghost_type)); } /// loop on each quadrature point for (; traction_it != traction_end; ++traction_it, ++opening_it, ++opening_prec_it, ++contact_traction_it, ++contact_opening_it, ++normal_it, ++sigma_c_it, ++delta_n_max_it, ++delta_t_max_it, ++delta_c_it, ++damage_n_it, ++damage_t_it, ++insertion_stress_it, ++reduction_penalty_it) { Real normal_opening_norm, tangential_opening_norm; bool penetration; Real current_penalty = 0.; Real delta_c2_R2 = *delta_c_it * (*delta_c_it) / R / R; /// compute normal and tangential opening vectors normal_opening_norm = opening_it->dot(*normal_it); Vector<Real> normal_opening = *normal_it; normal_opening *= normal_opening_norm; // std::cout<< "normal_opening_norm = " << normal_opening_norm <<std::endl; Vector<Real> tangential_opening = *opening_it; tangential_opening -= normal_opening; tangential_opening_norm = tangential_opening.norm(); /// compute effective opening displacement Real delta_n = tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2; Real delta_t = tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2; penetration = normal_opening_norm < 0.0; if (this->contact_after_breaking == false && Math::are_float_equal(*damage_n_it, 1.)) penetration = false; /** * If during the convergence loop a cohesive element continues to * jumps from penetration to opening, and convergence is not * reached, its penalty parameter will be reduced in the * recomputation of the same incremental step. Recompute is set * equal to true when convergence is not reached in the * solveStepCohesive function and the execution of the program * goes back to the main file where the variable load_reduction * is set equal to true. */ Real normal_opening_prec_norm = opening_prec_it->dot(*normal_it); // Vector<Real> normal_opening_prec = *normal_it; // normal_opening_prec *= normal_opening_prec_norm; if (!this->model->isExplicit()) // && !this->recompute) if ((normal_opening_prec_norm * normal_opening_norm) < 0.0) *reduction_penalty_it = true; *opening_prec_it = *opening_it; if (penetration) { if (this->recompute && *reduction_penalty_it){ /// the penalty parameter is locally reduced current_penalty = this->penalty / 100.; } else current_penalty = this->penalty; /// use penalty coefficient in case of penetration *contact_traction_it = normal_opening; *contact_traction_it *= current_penalty; *contact_opening_it = normal_opening; /// don't consider penetration contribution for delta *opening_it = tangential_opening; normal_opening.clear(); } else { delta_n += normal_opening_norm * normal_opening_norm; delta_t += normal_opening_norm * normal_opening_norm * delta_c2_R2; contact_traction_it->clear(); contact_opening_it->clear(); } delta_n = std::sqrt(delta_n); delta_t = std::sqrt(delta_t); /// update maximum displacement and damage *delta_n_max_it = std::max(*delta_n_max_it, delta_n); *damage_n_it = std::min(*delta_n_max_it / *delta_c_it, Real(1.)); *delta_t_max_it = std::max(*delta_t_max_it, delta_t); *damage_t_it = std::min(*delta_t_max_it / *delta_c_it, Real(1.)); Vector<Real> normal_traction(spatial_dimension); Vector<Real> shear_traction(spatial_dimension); /// NORMAL TRACTIONS if (Math::are_float_equal(*damage_n_it, 1.)) normal_traction.clear(); else if (Math::are_float_equal(*damage_n_it, 0.)) { if (penetration) normal_traction.clear(); else normal_traction = *insertion_stress_it; } else { // the following formulation holds both in loading and in // unloading-reloading normal_traction = normal_opening; AKANTU_DEBUG_ASSERT(*delta_n_max_it != 0., "Division by zero, tolerance might be too low"); normal_traction *= *sigma_c_it / (*delta_n_max_it) * (1. - *damage_n_it); } /// SHEAR TRACTIONS if (Math::are_float_equal(*damage_t_it, 1.)) shear_traction.clear(); else if (Math::are_float_equal(*damage_t_it, 0.)) { shear_traction.clear(); } else { shear_traction = tangential_opening; AKANTU_DEBUG_ASSERT(*delta_t_max_it != 0., "Division by zero, tolerance might be too low"); shear_traction *= this->beta2_kappa; shear_traction *= *sigma_c_it / (*delta_t_max_it) * (1. - *damage_t_it); } *traction_it = normal_traction; *traction_it += shear_traction; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinearUncoupled<spatial_dimension>::checkDeltaMax(GhostType ghost_type) { AKANTU_DEBUG_IN(); /** * This function set a predefined value to the parameter * delta_max_prev of the elements that have been inserted in the * last loading step for which convergence has not been * reached. This is done before reducing the loading and re-doing * the step. Otherwise, the updating of delta_max_prev would be * done with reference to the non-convergent solution. In this * function also other variables related to the contact and * friction behavior are correctly set. */ Mesh & mesh = this->fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); /** * the variable "recompute" is set to true to activate the * procedure that reduces the penalty parameter for * compression. This procedure is available only during the phase of * load_reduction, that has to be set in the main file. The * penalty parameter will be reduced only for the elements having * reduction_penalty = true. */ this->recompute = true; for(; it != last_type; ++it) { Array<UInt> & elem_filter = this->element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element == 0) continue; ElementType el_type = *it; // std::cout << "element type: " << el_type << std::endl; /// define iterators Array<Real>::scalar_iterator delta_n_max_it = delta_n_max(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_n_max_end = delta_n_max(el_type, ghost_type).end(); Array<Real>::scalar_iterator delta_n_max_prev_it = delta_n_max.previous(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_t_max_it = delta_t_max(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_t_max_prev_it = delta_t_max.previous(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_c_it = this-> delta_c_eff(el_type, ghost_type).begin(); Array<Real>::vector_iterator opening_prec_it = this->opening_prec(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator opening_prec_prev_it = this->opening_prec.previous(el_type, ghost_type).begin(spatial_dimension); Int it = 0; /// loop on each quadrature point for (; delta_n_max_it != delta_n_max_end; ++delta_n_max_it, ++delta_t_max_it, ++delta_c_it, ++delta_n_max_prev_it, ++delta_t_max_prev_it, ++opening_prec_it, ++opening_prec_prev_it) { ++it; if (*delta_n_max_prev_it == 0){ /// elements inserted in the last incremental step, that did /// not converge *delta_n_max_it = *delta_c_it / 1000.; } else /// elements introduced in previous incremental steps, for /// which a correct value of delta_max_prev already exists *delta_n_max_it = *delta_n_max_prev_it; if (*delta_t_max_prev_it == 0){ *delta_t_max_it = *delta_c_it * this->kappa / this->beta / 1000.; } else *delta_t_max_it = *delta_t_max_prev_it; /// in case convergence is not reached, set opening_prec to the /// value referred to the previous incremental step *opening_prec_it = *opening_prec_prev_it; } } } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinearUncoupled<spatial_dimension>::computeTangentTraction(const ElementType & el_type, Array<Real> & tangent_matrix, const Array<Real> & normal, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array<Real>::matrix_iterator tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension); Array<Real>::const_vector_iterator normal_it = this->normal.begin(spatial_dimension); Array<Real>::vector_iterator opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension); /// NB: delta_max_it points on delta_max_previous, i.e. the /// delta_max related to the solution of the previous incremental /// step Array<Real>::scalar_iterator delta_n_max_it = delta_n_max.previous(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_t_max_it = delta_t_max.previous(el_type, ghost_type).begin(); Array<Real>::scalar_iterator sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_c_it = this->delta_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator damage_n_it = damage_n(el_type, ghost_type).begin(); Array<Real>::vector_iterator contact_opening_it = this->contact_opening(el_type, ghost_type).begin(spatial_dimension); Array<bool>::scalar_iterator reduction_penalty_it = this->reduction_penalty(el_type, ghost_type).begin(); Vector<Real> normal_opening(spatial_dimension); Vector<Real> tangential_opening(spatial_dimension); for (; tangent_it != tangent_end; ++tangent_it, ++normal_it, ++opening_it, ++sigma_c_it, ++delta_c_it, ++delta_n_max_it, ++delta_t_max_it, ++damage_n_it, ++contact_opening_it, ++reduction_penalty_it) { Real normal_opening_norm, tangential_opening_norm; bool penetration; Real current_penalty = 0.; Real delta_c2_R2 = *delta_c_it * (*delta_c_it) / R / R; /** * During the update of the residual the interpenetrations are * stored in the array "contact_opening", therefore, in the case * of penetration, in the array "opening" there are only the * tangential components. */ *opening_it += *contact_opening_it; /// compute normal and tangential opening vectors normal_opening_norm = opening_it->dot(*normal_it); Vector<Real> normal_opening = *normal_it; normal_opening *= normal_opening_norm; Vector<Real> tangential_opening = *opening_it; tangential_opening -= normal_opening; tangential_opening_norm = tangential_opening.norm(); Real delta_n = tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2; Real delta_t = tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2; penetration = normal_opening_norm < 0.0; if (this->contact_after_breaking == false && Math::are_float_equal(*damage_n_it, 1.)) penetration = false; Real derivative = 0; // derivative = d(t/delta)/ddelta Real T = 0; /// TANGENT STIFFNESS FOR NORMAL TRACTIONS Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension); n_outer_n.outerProduct(*normal_it, *normal_it); if (penetration){ if (this->recompute && *reduction_penalty_it) current_penalty = this->penalty / 100.; else current_penalty = this->penalty; /// stiffness in compression given by the penalty parameter *tangent_it = n_outer_n; *tangent_it *= current_penalty; *opening_it = tangential_opening; normal_opening.clear(); } else{ delta_n += normal_opening_norm * normal_opening_norm; delta_n = std::sqrt(delta_n); delta_t += normal_opening_norm * normal_opening_norm * delta_c2_R2; /** * Delta has to be different from 0 to have finite values of * tangential stiffness. At the element insertion, delta = * 0. Therefore, a fictictious value is defined, for the * evaluation of the first value of K. */ if (delta_n < Math::getTolerance()) delta_n = *delta_c_it / 1000.; // loading if (delta_n >= *delta_n_max_it){ if (delta_n <= *delta_c_it){ derivative = - (*sigma_c_it) / (delta_n * delta_n); T = *sigma_c_it * (1 - delta_n / *delta_c_it); } else { derivative = 0.; T = 0.; } // unloading-reloading } else if (delta_n < *delta_n_max_it){ Real T_max = *sigma_c_it * (1 - *delta_n_max_it / *delta_c_it); derivative = 0.; T = T_max / *delta_n_max_it * delta_n; } /// computation of the derivative of the constitutive law (dT/ddelta) Matrix<Real> nn(n_outer_n); nn *= T / delta_n; Vector<Real> Delta_tilde(normal_opening); Delta_tilde *= (1. - this->beta2_kappa2); Vector<Real> mm(*opening_it); mm *= this->beta2_kappa2; Delta_tilde += mm; Vector<Real> Delta_hat(normal_opening); Matrix<Real> prov(spatial_dimension, spatial_dimension); prov.outerProduct(Delta_hat, Delta_tilde); prov *= derivative / delta_n; prov += nn; Matrix<Real> prov_t = prov.transpose(); *tangent_it = prov_t; } derivative = 0.; T = 0.; /// TANGENT STIFFNESS FOR SHEAR TRACTIONS delta_t = std::sqrt(delta_t); /** * Delta has to be different from 0 to have finite values of * tangential stiffness. At the element insertion, delta = * 0. Therefore, a fictictious value is defined, for the * evaluation of the first value of K. */ if (delta_t < Math::getTolerance()) delta_t = *delta_c_it / 1000.; // loading if (delta_t >= *delta_t_max_it){ if (delta_t <= *delta_c_it){ derivative = - (*sigma_c_it) / (delta_t * delta_t); T = *sigma_c_it * (1 - delta_t / *delta_c_it); } else { derivative = 0.; T = 0.; } // unloading-reloading } else if (delta_t < *delta_t_max_it){ Real T_max = *sigma_c_it * (1 - *delta_t_max_it / *delta_c_it); derivative = 0.; T = T_max / *delta_t_max_it * delta_t; } /// computation of the derivative of the constitutive law (dT/ddelta) Matrix<Real> I(spatial_dimension, spatial_dimension); I.eye(); Matrix<Real> nn(n_outer_n); I -= nn; I *= T / delta_t; Vector<Real> Delta_tilde(normal_opening); Delta_tilde *= (delta_c2_R2 - this->beta2_kappa2); Vector<Real> mm(*opening_it); mm *= this->beta2_kappa2; Delta_tilde += mm; Vector<Real> Delta_hat(tangential_opening); Delta_hat *= this->beta2_kappa; Matrix<Real> prov(spatial_dimension, spatial_dimension); prov.outerProduct(Delta_hat, Delta_tilde); prov *= derivative / delta_t; prov += I; Matrix<Real> prov_t = prov.transpose(); *tangent_it += prov_t; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialCohesiveLinearUncoupled); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.hh b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.hh index 393d151ab..1c5b2dfbe 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.hh +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.hh @@ -1,115 +1,115 @@ /** * @file material_cohesive_linear.hh * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Jan 14 2016 * * @brief Linear irreversible cohesive law of mixed mode loading with * random stress definition for extrinsic type * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_cohesive_linear.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_COHESIVE_LINEAR_UNCOUPLED_HH__ #define __AKANTU_MATERIAL_COHESIVE_LINEAR_UNCOUPLED_HH__ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /** * Cohesive material linear with two different laws for mode I and * mode II, for extrinsic case * * parameters in the material files : * - roughness : define the interaction between mode I and mode II (default: 0) */ template<UInt spatial_dimension> class MaterialCohesiveLinearUncoupled : public MaterialCohesiveLinear<spatial_dimension> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ // typedef MaterialCohesiveLinear<spatial_dimension> MaterialParent; public: MaterialCohesiveLinearUncoupled(SolidMechanicsModel & model, const ID & id = ""); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the material parameters virtual void initMaterial(); protected: /// constitutive law virtual void computeTraction(const Array<Real> & normal, ElementType el_type, GhostType ghost_type = _not_ghost); /// check delta_max for cohesive elements in case of no convergence /// in the solveStep (only for extrinsic-implicit) virtual void checkDeltaMax(GhostType ghost_type = _not_ghost); /// compute tangent stiffness matrix virtual void computeTangentTraction(const ElementType & el_type, Array<Real> & tangent_matrix, const Array<Real> & normal, GhostType ghost_type); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// parameter to tune the interaction between mode II and mode I Real R; /// maximum normal displacement CohesiveInternalField<Real> delta_n_max; /// maximum tangential displacement CohesiveInternalField<Real> delta_t_max; /// damage associated to normal tractions CohesiveInternalField<Real> damage_n; /// damage associated to shear tractions CohesiveInternalField<Real> damage_t; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_COHESIVE_LINEAR_UNCOUPLED_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.cc b/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.cc index e4bf64f71..d32efadc0 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.cc @@ -1,616 +1,616 @@ /** * @file material_cohesive.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Feb 22 2012 * @date last modification: Tue Jan 12 2016 * * @brief Specialization of the material class for cohesive elements * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_cohesive.hh" #include "aka_random_generator.hh" #include "dof_synchronizer.hh" #include "shape_cohesive.hh" #include "solid_mechanics_model_cohesive.hh" #include "sparse_matrix.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ MaterialCohesive::MaterialCohesive(SolidMechanicsModel & model, const ID & id) : Material(model, id), facet_filter("facet_filter", id, this->getMemoryID()), fem_cohesive(&( model.getFEEngineClass<MyFEEngineCohesiveType>("CohesiveFEEngine"))), reversible_energy("reversible_energy", *this), total_energy("total_energy", *this), opening("opening", *this), opening_old("opening (old)", *this), tractions("tractions", *this), tractions_old("tractions (old)", *this), contact_tractions("contact_tractions", *this), contact_opening("contact_opening", *this), delta_max("delta max", *this), use_previous_delta_max(false), use_previous_opening(false), damage("damage", *this), sigma_c("sigma_c", *this), normal(0, spatial_dimension, "normal") { AKANTU_DEBUG_IN(); this->model = dynamic_cast<SolidMechanicsModelCohesive *>(&model); this->registerParam("sigma_c", sigma_c, _pat_parsable | _pat_readable, "Critical stress"); this->registerParam("delta_c", delta_c, Real(0.), _pat_parsable | _pat_readable, "Critical displacement"); this->model->getMesh().initElementTypeMapArray( this->element_filter, 1, spatial_dimension, false, _ek_cohesive); if (this->model->getIsExtrinsic()) this->model->getMeshFacets().initElementTypeMapArray(facet_filter, 1, spatial_dimension - 1); this->reversible_energy.initialize(1); this->total_energy.initialize(1); this->tractions_old.initialize(spatial_dimension); this->tractions.initialize(spatial_dimension); this->opening_old.initialize(spatial_dimension); this->contact_tractions.initialize(spatial_dimension); this->contact_opening.initialize(spatial_dimension); this->opening.initialize(spatial_dimension); this->delta_max.initialize(1); this->damage.initialize(1); if (this->model->getIsExtrinsic()) this->sigma_c.initialize(1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ MaterialCohesive::~MaterialCohesive() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialCohesive::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); if (this->use_previous_delta_max) this->delta_max.initializeHistory(); if (this->use_previous_opening) this->opening.initializeHistory(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialCohesive::assembleInternalForces(GhostType ghost_type) { AKANTU_DEBUG_IN(); #if defined(AKANTU_DEBUG_TOOLS) debug::element_manager.printData(debug::_dm_material_cohesive, "Cohesive Tractions", tractions); #endif Array<Real> & residual = const_cast<Array<Real> &>(model->getInternalForce()); Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); for (; it != last_type; ++it) { Array<UInt> & elem_filter = element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element == 0) continue; const Array<Real> & shapes = fem_cohesive->getShapes(*it, ghost_type); Array<Real> & traction = tractions(*it, ghost_type); Array<Real> & contact_traction = contact_tractions(*it, ghost_type); UInt size_of_shapes = shapes.getNbComponent(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); UInt nb_quadrature_points = fem_cohesive->getNbIntegrationPoints(*it, ghost_type); /// compute @f$t_i N_a@f$ Array<Real> * traction_cpy = new Array<Real>( nb_element * nb_quadrature_points, spatial_dimension * size_of_shapes); Array<Real>::iterator<Matrix<Real> > traction_it = traction.begin(spatial_dimension, 1); Array<Real>::iterator<Matrix<Real> > contact_traction_it = contact_traction.begin(spatial_dimension, 1); Array<Real>::const_iterator<Matrix<Real> > shapes_filtered_begin = shapes.begin(1, size_of_shapes); Array<Real>::iterator<Matrix<Real> > traction_cpy_it = traction_cpy->begin(spatial_dimension, size_of_shapes); Matrix<Real> traction_tmp(spatial_dimension, 1); for (UInt el = 0; el < nb_element; ++el) { UInt current_quad = elem_filter(el) * nb_quadrature_points; for (UInt q = 0; q < nb_quadrature_points; ++q, ++traction_it, ++contact_traction_it, ++current_quad, ++traction_cpy_it) { const Matrix<Real> & shapes_filtered = shapes_filtered_begin[current_quad]; traction_tmp.copy(*traction_it); traction_tmp += *contact_traction_it; traction_cpy_it->mul<false, false>(traction_tmp, shapes_filtered); } } /** * compute @f$\int t \cdot N\, dS@f$ by @f$ \sum_q \mathbf{N}^t * \mathbf{t}_q \overline w_q J_q@f$ */ Array<Real> * int_t_N = new Array<Real>( nb_element, spatial_dimension * size_of_shapes, "int_t_N"); fem_cohesive->integrate(*traction_cpy, *int_t_N, spatial_dimension * size_of_shapes, *it, ghost_type, elem_filter); delete traction_cpy; int_t_N->extendComponentsInterlaced(2, int_t_N->getNbComponent()); Real * int_t_N_val = int_t_N->storage(); for (UInt el = 0; el < nb_element; ++el) { for (UInt n = 0; n < size_of_shapes * spatial_dimension; ++n) int_t_N_val[n] *= -1.; int_t_N_val += nb_nodes_per_element * spatial_dimension; } /// assemble model->getFEEngineBoundary().assembleArray( *int_t_N, residual, model->getDOFSynchronizer().getLocalDOFEquationNumbers(), residual.getNbComponent(), *it, ghost_type, elem_filter, 1); delete int_t_N; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialCohesive::assembleStiffnessMatrix(GhostType ghost_type) { AKANTU_DEBUG_IN(); SparseMatrix & K = const_cast<SparseMatrix &>(model->getStiffnessMatrix()); Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); for (; it != last_type; ++it) { UInt nb_quadrature_points = fem_cohesive->getNbIntegrationPoints(*it, ghost_type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); const Array<Real> & shapes = fem_cohesive->getShapes(*it, ghost_type); Array<UInt> & elem_filter = element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (!nb_element) continue; UInt size_of_shapes = shapes.getNbComponent(); Array<Real> * shapes_filtered = new Array<Real>( nb_element * nb_quadrature_points, size_of_shapes, "filtered shapes"); Real * shapes_val = shapes.storage(); Real * shapes_filtered_val = shapes_filtered->storage(); UInt * elem_filter_val = elem_filter.storage(); for (UInt el = 0; el < nb_element; ++el) { shapes_val = shapes.storage() + elem_filter_val[el] * size_of_shapes * nb_quadrature_points; memcpy(shapes_filtered_val, shapes_val, size_of_shapes * nb_quadrature_points * sizeof(Real)); shapes_filtered_val += size_of_shapes * nb_quadrature_points; } /** * compute A matrix @f$ \mathbf{A} = \left[\begin{array}{c c c c c c c c c c *c c} * 1 & 0 & 0 & 0 & 0 & 0 & -1 & 0 & 0 & 0 & 0 & 0 \\ * 0 & 1 & 0 & 0 & 0 & 0 & 0 & -1 & 0 & 0 & 0 & 0 \\ * 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & -1 & 0 & 0 & 0 \\ * 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & -1 & 0 & 0 \\ * 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & -1 & 0 \\ * 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & -1 * \end{array} \right]@f$ **/ // UInt size_of_A = // spatial_dimension*size_of_shapes*spatial_dimension*nb_nodes_per_element; // Real * A = new Real[size_of_A]; // memset(A, 0, size_of_A*sizeof(Real)); Matrix<Real> A(spatial_dimension * size_of_shapes, spatial_dimension * nb_nodes_per_element); for (UInt i = 0; i < spatial_dimension * size_of_shapes; ++i) { A(i, i) = 1; A(i, i + spatial_dimension * size_of_shapes) = -1; } // compute traction. This call is not necessary for the linear // cohesive law that, currently, is the only one used for the // extrinsic approach. // if (!model->getIsExtrinsic()){ // computeTraction(ghost_type); //} /// get the tangent matrix @f$\frac{\partial{(t/\delta)}}{\partial{\delta}} /// @f$ Array<Real> * tangent_stiffness_matrix = new Array<Real>( nb_element * nb_quadrature_points, spatial_dimension * spatial_dimension, "tangent_stiffness_matrix"); // Array<Real> * normal = new Array<Real>(nb_element * // nb_quadrature_points, spatial_dimension, "normal"); normal.resize(nb_quadrature_points); model->updateCurrentPosition(); computeNormal(model->getCurrentPosition(), normal, *it, ghost_type); /// compute openings @f$\mathbf{\delta}@f$ // computeOpening(model->getDisplacement(), opening(*it, ghost_type), *it, // ghost_type); tangent_stiffness_matrix->clear(); computeTangentTraction(*it, *tangent_stiffness_matrix, normal, ghost_type); // delete normal; UInt size_at_nt_d_n_a = spatial_dimension * nb_nodes_per_element * spatial_dimension * nb_nodes_per_element; Array<Real> * at_nt_d_n_a = new Array<Real>( nb_element * nb_quadrature_points, size_at_nt_d_n_a, "A^t*N^t*D*N*A"); Array<Real>::iterator<Vector<Real> > shapes_filt_it = shapes_filtered->begin(size_of_shapes); Array<Real>::matrix_iterator D_it = tangent_stiffness_matrix->begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator At_Nt_D_N_A_it = at_nt_d_n_a->begin(spatial_dimension * nb_nodes_per_element, spatial_dimension * nb_nodes_per_element); Array<Real>::matrix_iterator At_Nt_D_N_A_end = at_nt_d_n_a->end(spatial_dimension * nb_nodes_per_element, spatial_dimension * nb_nodes_per_element); Matrix<Real> N(spatial_dimension, spatial_dimension * size_of_shapes); Matrix<Real> N_A(spatial_dimension, spatial_dimension * nb_nodes_per_element); Matrix<Real> D_N_A(spatial_dimension, spatial_dimension * nb_nodes_per_element); for (; At_Nt_D_N_A_it != At_Nt_D_N_A_end; ++At_Nt_D_N_A_it, ++D_it, ++shapes_filt_it) { N.clear(); /** * store the shapes in voigt notations matrix @f$\mathbf{N} = * \begin{array}{cccccc} N_0(\xi) & 0 & N_1(\xi) &0 & N_2(\xi) & 0 \\ * 0 & * N_0(\xi)& 0 &N_1(\xi)& 0 & N_2(\xi) \end{array} @f$ **/ for (UInt i = 0; i < spatial_dimension; ++i) for (UInt n = 0; n < size_of_shapes; ++n) N(i, i + spatial_dimension * n) = (*shapes_filt_it)(n); /** * compute stiffness matrix @f$ \mathbf{K} = \delta \mathbf{U}^T * \int_{\Gamma_c} {\mathbf{P}^t \frac{\partial{\mathbf{t}}} *{\partial{\delta}} * \mathbf{P} d\Gamma \Delta \mathbf{U}} @f$ **/ N_A.mul<false, false>(N, A); D_N_A.mul<false, false>(*D_it, N_A); (*At_Nt_D_N_A_it).mul<true, false>(D_N_A, N_A); } delete tangent_stiffness_matrix; delete shapes_filtered; Array<Real> * K_e = new Array<Real>(nb_element, size_at_nt_d_n_a, "K_e"); fem_cohesive->integrate(*at_nt_d_n_a, *K_e, size_at_nt_d_n_a, *it, ghost_type, elem_filter); delete at_nt_d_n_a; model->getFEEngine().assembleMatrix(*K_e, K, spatial_dimension, *it, ghost_type, elem_filter); delete K_e; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- * * Compute traction from displacements * * @param[in] ghost_type compute the residual for _ghost or _not_ghost element */ void MaterialCohesive::computeTraction(GhostType ghost_type) { AKANTU_DEBUG_IN(); #if defined(AKANTU_DEBUG_TOOLS) debug::element_manager.printData(debug::_dm_material_cohesive, "Cohesive Openings", opening); #endif Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); for (; it != last_type; ++it) { Array<UInt> & elem_filter = element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element == 0) continue; UInt nb_quadrature_points = nb_element * fem_cohesive->getNbIntegrationPoints(*it, ghost_type); normal.resize(nb_quadrature_points); /// compute normals @f$\mathbf{n}@f$ model->updateCurrentPosition(); computeNormal(model->getCurrentPosition(), normal, *it, ghost_type); /// compute openings @f$\mathbf{\delta}@f$ computeOpening(model->getDisplacement(), opening(*it, ghost_type), *it, ghost_type); /// compute traction @f$\mathbf{t}@f$ computeTraction(normal, *it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialCohesive::computeNormal(const Array<Real> & position, Array<Real> & normal, ElementType type, GhostType ghost_type) { AKANTU_DEBUG_IN(); if (type == _cohesive_1d_2) fem_cohesive->computeNormalsOnIntegrationPoints(position, normal, type, ghost_type); else { #define COMPUTE_NORMAL(type) \ fem_cohesive->getShapeFunctions() \ .computeNormalsOnIntegrationPoints<type, CohesiveReduceFunctionMean>( \ position, normal, ghost_type, element_filter(type, ghost_type)); AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(COMPUTE_NORMAL); #undef COMPUTE_NORMAL } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialCohesive::computeOpening(const Array<Real> & displacement, Array<Real> & opening, ElementType type, GhostType ghost_type) { AKANTU_DEBUG_IN(); #define COMPUTE_OPENING(type) \ fem_cohesive->getShapeFunctions() \ .interpolateOnIntegrationPoints<type, CohesiveReduceFunctionOpening>( \ displacement, opening, spatial_dimension, ghost_type, \ element_filter(type, ghost_type)); AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(COMPUTE_OPENING); #undef COMPUTE_OPENING AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialCohesive::computeEnergies() { AKANTU_DEBUG_IN(); Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _not_ghost, _ek_cohesive); Real * memory_space = new Real[2 * spatial_dimension]; Vector<Real> b(memory_space, spatial_dimension); Vector<Real> h(memory_space + spatial_dimension, spatial_dimension); for (; it != last_type; ++it) { Array<Real>::iterator<Real> erev = reversible_energy(*it, _not_ghost).begin(); Array<Real>::iterator<Real> etot = total_energy(*it, _not_ghost).begin(); Array<Real>::vector_iterator traction_it = tractions(*it, _not_ghost).begin(spatial_dimension); Array<Real>::vector_iterator traction_old_it = tractions_old(*it, _not_ghost).begin(spatial_dimension); Array<Real>::vector_iterator opening_it = opening(*it, _not_ghost).begin(spatial_dimension); Array<Real>::vector_iterator opening_old_it = opening_old(*it, _not_ghost).begin(spatial_dimension); Array<Real>::vector_iterator traction_end = tractions(*it, _not_ghost).end(spatial_dimension); /// loop on each quadrature point for (; traction_it != traction_end; ++traction_it, ++traction_old_it, ++opening_it, ++opening_old_it, ++erev, ++etot) { /// trapezoidal integration b = *opening_it; b -= *opening_old_it; h = *traction_old_it; h += *traction_it; *etot += .5 * b.dot(h); *erev = .5 * traction_it->dot(*opening_it); } } delete[] memory_space; /// update old values it = mesh.firstType(spatial_dimension, _not_ghost, _ek_cohesive); GhostType ghost_type = _not_ghost; for (; it != last_type; ++it) { tractions_old(*it, ghost_type).copy(tractions(*it, ghost_type)); opening_old(*it, ghost_type).copy(opening(*it, ghost_type)); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real MaterialCohesive::getReversibleEnergy() { AKANTU_DEBUG_IN(); Real erev = 0.; /// integrate reversible energy for each type of elements Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _not_ghost, _ek_cohesive); for (; it != last_type; ++it) { erev += fem_cohesive->integrate(reversible_energy(*it, _not_ghost), *it, _not_ghost, element_filter(*it, _not_ghost)); } AKANTU_DEBUG_OUT(); return erev; } /* -------------------------------------------------------------------------- */ Real MaterialCohesive::getDissipatedEnergy() { AKANTU_DEBUG_IN(); Real edis = 0.; /// integrate dissipated energy for each type of elements Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _not_ghost, _ek_cohesive); for (; it != last_type; ++it) { Array<Real> dissipated_energy(total_energy(*it, _not_ghost)); dissipated_energy -= reversible_energy(*it, _not_ghost); edis += fem_cohesive->integrate(dissipated_energy, *it, _not_ghost, element_filter(*it, _not_ghost)); } AKANTU_DEBUG_OUT(); return edis; } /* -------------------------------------------------------------------------- */ Real MaterialCohesive::getContactEnergy() { AKANTU_DEBUG_IN(); Real econ = 0.; /// integrate contact energy for each type of elements Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _not_ghost, _ek_cohesive); for (; it != last_type; ++it) { Array<UInt> & el_filter = element_filter(*it, _not_ghost); UInt nb_quad_per_el = fem_cohesive->getNbIntegrationPoints(*it, _not_ghost); UInt nb_quad_points = el_filter.getSize() * nb_quad_per_el; Array<Real> contact_energy(nb_quad_points); Array<Real>::vector_iterator contact_traction_it = contact_tractions(*it, _not_ghost).begin(spatial_dimension); Array<Real>::vector_iterator contact_opening_it = contact_opening(*it, _not_ghost).begin(spatial_dimension); /// loop on each quadrature point for (UInt el = 0; el < nb_quad_points; ++contact_traction_it, ++contact_opening_it, ++el) { contact_energy(el) = .5 * contact_traction_it->dot(*contact_opening_it); } econ += fem_cohesive->integrate(contact_energy, *it, _not_ghost, el_filter); } AKANTU_DEBUG_OUT(); return econ; } /* -------------------------------------------------------------------------- */ Real MaterialCohesive::getEnergy(std::string type) { AKANTU_DEBUG_IN(); if (type == "reversible") return getReversibleEnergy(); else if (type == "dissipated") return getDissipatedEnergy(); else if (type == "cohesive contact") return getContactEnergy(); AKANTU_DEBUG_OUT(); return 0.; } /* -------------------------------------------------------------------------- */ - __END_AKANTU__ + } // akantu diff --git a/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.hh b/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.hh index eb963b128..981ec2cd5 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.hh +++ b/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.hh @@ -1,266 +1,266 @@ /** * @file material_cohesive.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Jan 12 2016 * * @brief Specialization of the material class for cohesive elements * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" #include "fe_engine_template.hh" #include "aka_common.hh" #include "cohesive_internal_field.hh" #include "cohesive_element_inserter.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_COHESIVE_HH__ #define __AKANTU_MATERIAL_COHESIVE_HH__ /* -------------------------------------------------------------------------- */ namespace akantu { class SolidMechanicsModelCohesive; } -__BEGIN_AKANTU__ +namespace akantu { class MaterialCohesive : public Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive> MyFEEngineCohesiveType; public: MaterialCohesive(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialCohesive(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the material computed parameter virtual void initMaterial(); /// compute tractions (including normals and openings) void computeTraction(GhostType ghost_type = _not_ghost); /// assemble residual void assembleInternalForces(GhostType ghost_type = _not_ghost); /// compute reversible and total energies by element void computeEnergies(); /// check stress for cohesive elements' insertion, by default it /// also updates the cohesive elements' data virtual void checkInsertion(__attribute__((unused)) bool check_only = false) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// check delta_max for cohesive elements in case of no convergence /// in the solveStep (only for extrinsic-implicit) virtual void checkDeltaMax(__attribute__((unused)) GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// reset variables when convergence is reached (only for /// extrinsic-implicit) virtual void resetVariables(__attribute__((unused)) GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// interpolate stress on given positions for each element (empty /// implemantation to avoid the generic call to be done on cohesive elements) virtual void interpolateStress(__attribute__((unused)) const ElementType type, __attribute__((unused)) Array<Real> & result){}; /// compute the stresses virtual void computeAllStresses(__attribute__((unused)) GhostType ghost_type = _not_ghost){}; // add the facet to be handled by the material UInt addFacet(const Element & element); protected: virtual void computeTangentTraction(__attribute__((unused)) const ElementType & el_type, __attribute__((unused)) Array<Real> & tangent_matrix, __attribute__((unused)) const Array<Real> & normal, __attribute__((unused)) GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the normal void computeNormal(const Array<Real> & position, Array<Real> & normal, ElementType type, GhostType ghost_type); /// compute the opening void computeOpening(const Array<Real> & displacement, Array<Real> & opening, ElementType type, GhostType ghost_type); template <ElementType type> void computeNormal(const Array<Real> & position, Array<Real> & normal, GhostType ghost_type); /// assemble stiffness void assembleStiffnessMatrix(GhostType ghost_type); /// constitutive law virtual void computeTraction(const Array<Real> & normal, ElementType el_type, GhostType ghost_type = _not_ghost) = 0; /// parallelism functions inline UInt getNbDataForElements(const Array<Element> & elements, SynchronizationTag tag) const; inline void packElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag) const; inline void unpackElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the opening AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Opening, opening, Real); /// get the traction AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Traction, tractions, Real); /// get damage AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real); /// get facet filter AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(FacetFilter, facet_filter, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(FacetFilter, facet_filter, UInt); AKANTU_GET_MACRO(FacetFilter, facet_filter, const ElementTypeMapArray<UInt> &); // AKANTU_GET_MACRO(ElementFilter, element_filter, const // ElementTypeMapArray<UInt> &); /// compute reversible energy Real getReversibleEnergy(); /// compute dissipated energy Real getDissipatedEnergy(); /// compute contact energy Real getContactEnergy(); /// get energy virtual Real getEnergy(std::string type); /// return the energy (identified by id) for the provided element virtual Real getEnergy(std::string energy_id, ElementType type, UInt index) { return Material::getEnergy(energy_id, type, index); } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// list of facets assigned to this material ElementTypeMapArray<UInt> facet_filter; /// Link to the cohesive fem object in the model MyFEEngineCohesiveType * fem_cohesive; private: /// reversible energy by quadrature point CohesiveInternalField<Real> reversible_energy; /// total energy by quadrature point CohesiveInternalField<Real> total_energy; protected: /// opening in all elements and quadrature points CohesiveInternalField<Real> opening; /// opening in all elements and quadrature points (previous time step) CohesiveInternalField<Real> opening_old; /// traction in all elements and quadrature points CohesiveInternalField<Real> tractions; /// traction in all elements and quadrature points (previous time step) CohesiveInternalField<Real> tractions_old; /// traction due to contact CohesiveInternalField<Real> contact_tractions; /// normal openings for contact tractions CohesiveInternalField<Real> contact_opening; /// maximum displacement CohesiveInternalField<Real> delta_max; /// tell if the previous delta_max state is needed (in iterative schemes) bool use_previous_delta_max; /// tell if the previous opening state is needed (in iterative schemes) bool use_previous_opening; /// damage CohesiveInternalField<Real> damage; /// pointer to the solid mechanics model for cohesive elements SolidMechanicsModelCohesive * model; /// critical stress RandomInternalField<Real, FacetInternalField> sigma_c; /// critical displacement Real delta_c; /// array to temporarily store the normals Array<Real> normal; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_cohesive_inline_impl.cc" -__END_AKANTU__ +} // akantu #include "cohesive_internal_field_tmpl.hh" #endif /* __AKANTU_MATERIAL_COHESIVE_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_damage/material_damage.hh b/src/model/solid_mechanics/materials/material_damage/material_damage.hh index aace57a4c..3671ba428 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_damage.hh +++ b/src/model/solid_mechanics/materials/material_damage/material_damage.hh @@ -1,113 +1,113 @@ /** * @file material_damage.hh * * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sat Jul 11 2015 * * @brief Material isotropic elastic * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_elastic.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_DAMAGE_HH__ #define __AKANTU_MATERIAL_DAMAGE_HH__ -__BEGIN_AKANTU__ +namespace akantu { template <UInt spatial_dimension, template <UInt> class Parent = MaterialElastic> class MaterialDamage : public Parent<spatial_dimension> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialDamage(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialDamage(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void initMaterial(); /// compute the tangent stiffness matrix for an element type virtual void computeTangentModuli(const ElementType & el_type, Array<Real> & tangent_matrix, GhostType ghost_type = _not_ghost); virtual bool hasStiffnessMatrixChanged() { return true; } protected: /// update the dissipated energy, must be called after the stress have been /// computed virtual void updateEnergies(ElementType el_type, GhostType ghost_type); /// compute the tangent stiffness matrix for a given quadrature point inline void computeTangentModuliOnQuad(Matrix<Real> & tangent, Real & dam); /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// give the dissipated energy for the time step Real getDissipatedEnergy() const; virtual Real getEnergy(std::string type); virtual Real getEnergy(std::string energy_id, ElementType type, UInt index) { return Parent<spatial_dimension>::getEnergy(energy_id, type, index); }; AKANTU_GET_MACRO_NOT_CONST(Damage, damage, ElementTypeMapArray<Real> &); AKANTU_GET_MACRO(Damage, damage, const ElementTypeMapArray<Real> &); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real) /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// damage internal variable InternalField<Real> damage; /// dissipated energy InternalField<Real> dissipated_energy; /// contain the current value of @f$ \int_0^{\epsilon}\sigma(\omega)d\omega /// @f$ the dissipated energy InternalField<Real> int_sigma; }; -__END_AKANTU__ +} // akantu #include "material_damage_tmpl.hh" #endif /* __AKANTU_MATERIAL_DAMAGE_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_damage/material_damage_non_local.hh b/src/model/solid_mechanics/materials/material_damage/material_damage_non_local.hh index cc2a92e95..500ad4bb2 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_damage_non_local.hh +++ b/src/model/solid_mechanics/materials/material_damage/material_damage_non_local.hh @@ -1,108 +1,108 @@ /** * @file material_damage_non_local.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Aug 23 2012 * @date last modification: Wed Oct 21 2015 * * @brief interface for non local damage material * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_non_local.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_DAMAGE_NON_LOCAL_HH__ #define __AKANTU_MATERIAL_DAMAGE_NON_LOCAL_HH__ -__BEGIN_AKANTU__ +namespace akantu { template <UInt spatial_dimension, class MaterialDamageLocal> class MaterialDamageNonLocal : public MaterialDamageLocal, public MaterialNonLocal<spatial_dimension> { public: typedef MaterialNonLocal<spatial_dimension> MaterialNonLocalParent; typedef MaterialDamageLocal MaterialDamageParent; MaterialDamageNonLocal(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialDamageParent(model, id), MaterialNonLocalParent(model, id){}; /* ------------------------------------------------------------------------ */ virtual void initMaterial() { MaterialDamageParent::initMaterial(); MaterialNonLocalParent::initMaterial(); } protected: /* -------------------------------------------------------------------------- */ virtual void computeNonLocalStress(ElementType type, GhostType ghost_type = _not_ghost) = 0; /* ------------------------------------------------------------------------ */ void computeNonLocalStresses(GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh::type_iterator it = this->model->getFEEngine().getMesh().firstType( spatial_dimension, ghost_type); Mesh::type_iterator last_type = this->model->getFEEngine().getMesh().lastType(spatial_dimension, ghost_type); for (; it != last_type; ++it) { Array<UInt> & elem_filter = this->element_filter(*it, ghost_type); if (elem_filter.getSize() == 0) continue; computeNonLocalStress(*it, ghost_type); } AKANTU_DEBUG_OUT(); } public: /* ------------------------------------------------------------------------ */ virtual inline UInt getNbDataForElements(const Array<Element> & elements, SynchronizationTag tag) const { return MaterialNonLocalParent::getNbDataForElements(elements, tag) + MaterialDamageParent::getNbDataForElements(elements, tag); } virtual inline void packElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag) const { MaterialNonLocalParent::packElementData(buffer, elements, tag); MaterialDamageParent::packElementData(buffer, elements, tag); } virtual inline void unpackElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag) { MaterialNonLocalParent::unpackElementData(buffer, elements, tag); MaterialDamageParent::unpackElementData(buffer, elements, tag); } }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_DAMAGE_NON_LOCAL_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_damage/material_damage_tmpl.hh b/src/model/solid_mechanics/materials/material_damage/material_damage_tmpl.hh index 54e0dc2a6..dc58b0d33 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_damage_tmpl.hh +++ b/src/model/solid_mechanics/materials/material_damage/material_damage_tmpl.hh @@ -1,173 +1,173 @@ /** * @file material_damage_tmpl.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Aug 18 2015 * * @brief Specialization of the material class for the damage material * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_damage.hh" #include "solid_mechanics_model.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension, template<UInt> class Parent> MaterialDamage<spatial_dimension, Parent>::MaterialDamage(SolidMechanicsModel & model, const ID & id) : Material(model, id), Parent<spatial_dimension>(model, id), damage("damage", *this), dissipated_energy("damage dissipated energy", *this), int_sigma("integral of sigma", *this) { AKANTU_DEBUG_IN(); this->is_non_local = false; this->use_previous_stress = true; this->use_previous_gradu = true; this->damage .initialize(1); this->dissipated_energy.initialize(1); this->int_sigma .initialize(1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension, template<UInt> class Parent> void MaterialDamage<spatial_dimension, Parent>::initMaterial() { AKANTU_DEBUG_IN(); Parent<spatial_dimension>::initMaterial(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Compute the dissipated energy in each element by a trapezoidal approximation * of * @f$ Ed = \int_0^{\epsilon}\sigma(\omega)d\omega - \frac{1}{2}\sigma:\epsilon@f$ */ template<UInt spatial_dimension, template<UInt> class Parent> void MaterialDamage<spatial_dimension, Parent>::updateEnergies(ElementType el_type, GhostType ghost_type) { Parent<spatial_dimension>::updateEnergies(el_type, ghost_type); this->computePotentialEnergy(el_type, ghost_type); Array<Real>::matrix_iterator epsilon_p = this->gradu.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator sigma_p = this->stress.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension); Array<Real>::const_scalar_iterator epot = this->potential_energy(el_type, ghost_type).begin(); Array<Real>::scalar_iterator ints = this->int_sigma(el_type, ghost_type).begin(); Array<Real>::scalar_iterator ed = this->dissipated_energy(el_type, ghost_type).begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix<Real> delta_gradu_it(*gradu_it); delta_gradu_it -= *epsilon_p; Matrix<Real> sigma_h(sigma); sigma_h += *sigma_p; Real dint = .5 * sigma_h.doubleDot(delta_gradu_it); *ints += dint; *ed = *ints - *epot; ++epsilon_p; ++sigma_p; ++epot; ++ints; ++ed; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension, template<UInt> class Parent> void MaterialDamage<spatial_dimension, Parent>::computeTangentModuli(const ElementType & el_type, Array<Real> & tangent_matrix, GhostType ghost_type) { AKANTU_DEBUG_IN(); Parent<spatial_dimension>::computeTangentModuli(el_type, tangent_matrix, ghost_type); Real * dam = this->damage(el_type, ghost_type).storage(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); computeTangentModuliOnQuad(tangent, *dam); ++dam; MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension, template<UInt> class Parent> void MaterialDamage<spatial_dimension, Parent>::computeTangentModuliOnQuad(Matrix<Real> & tangent, Real & dam) { tangent *= (1-dam); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension, template<UInt> class Parent> Real MaterialDamage<spatial_dimension, Parent>::getDissipatedEnergy() const { AKANTU_DEBUG_IN(); Real de = 0.; const Mesh & mesh = this->model->getFEEngine().getMesh(); /// integrate the dissipated energy for each type of elements Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost); Mesh::type_iterator end = mesh.lastType(spatial_dimension, _not_ghost); for(; it != end; ++it) { de += this->model->getFEEngine().integrate(dissipated_energy(*it, _not_ghost), *it, _not_ghost, this->element_filter(*it, _not_ghost)); } AKANTU_DEBUG_OUT(); return de; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension, template<UInt> class Parent> Real MaterialDamage<spatial_dimension, Parent>::getEnergy(std::string type) { if(type == "dissipated") return getDissipatedEnergy(); else return Parent<spatial_dimension>::getEnergy(type); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo.cc b/src/model/solid_mechanics/materials/material_damage/material_marigo.cc index 4088340ff..349e29fe5 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_marigo.cc +++ b/src/model/solid_mechanics/materials/material_damage/material_marigo.cc @@ -1,106 +1,106 @@ /** * @file material_marigo.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 08 2015 * * @brief Specialization of the material class for the marigo material * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_marigo.hh" #include "solid_mechanics_model.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialMarigo<spatial_dimension>::MaterialMarigo(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialDamage<spatial_dimension>(model, id), Yd("Yd", *this), damage_in_y(false), yc_limit(false) { AKANTU_DEBUG_IN(); this->registerParam("Sd", Sd, Real(5000.), _pat_parsable | _pat_modifiable); this->registerParam("epsilon_c", epsilon_c, Real(0.), _pat_parsable, "Critical strain"); this->registerParam("Yc limit", yc_limit, false, _pat_internal, "As the material a critical Y"); this->registerParam("damage_in_y", damage_in_y, false, _pat_parsable, "Use threshold (1-D)Y"); this->registerParam("Yd", Yd, _pat_parsable, "Damaging energy threshold"); this->Yd.initialize(1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialMarigo<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialDamage<spatial_dimension>::initMaterial(); updateInternalParameters(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialMarigo<spatial_dimension>::updateInternalParameters() { MaterialDamage<spatial_dimension>::updateInternalParameters(); Yc = .5 * epsilon_c * this->E * epsilon_c; if(std::abs(epsilon_c) > std::numeric_limits<Real>::epsilon()) yc_limit = true; else yc_limit = false; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialMarigo<spatial_dimension>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real>::scalar_iterator dam = this->damage(el_type, ghost_type).begin(); Array<Real>::scalar_iterator Yd_q = this->Yd(el_type, ghost_type) .begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Real Y = 0.; computeStressOnQuad(grad_u, sigma, *dam, Y, *Yd_q); ++dam; ++Yd_q; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } INSTANTIATE_MATERIAL(MaterialMarigo); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo.hh b/src/model/solid_mechanics/materials/material_damage/material_marigo.hh index 667662940..450eb7354 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_marigo.hh +++ b/src/model/solid_mechanics/materials/material_damage/material_marigo.hh @@ -1,124 +1,124 @@ /** * @file material_marigo.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief Marigo damage law * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" #include "material_damage.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_MARIGO_HH__ #define __AKANTU_MATERIAL_MARIGO_HH__ -__BEGIN_AKANTU__ +namespace akantu { /** * Material marigo * * parameters in the material files : * - Yd : (default: 50) * - Sd : (default: 5000) * - Ydrandomness : (default:0) */ template <UInt spatial_dimension> class MaterialMarigo : public MaterialDamage<spatial_dimension> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialMarigo(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialMarigo(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); virtual void updateInternalParameters(); /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); protected: /// constitutive law for a given quadrature point inline void computeStressOnQuad(Matrix<Real> & grad_u, Matrix<Real> & sigma, Real & dam, Real & Y, Real & Ydq); inline void computeDamageAndStressOnQuad(Matrix<Real> & sigma, Real & dam, Real & Y, Real & Ydq); /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ public: inline virtual UInt getNbData(const Array<Element> & elements, const SynchronizationTag & tag) const; inline virtual void packData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) const; inline virtual void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// resistance to damage RandomInternalField<Real> Yd; /// damage threshold Real Sd; /// critical epsilon when the material is considered as broken Real epsilon_c; Real Yc; bool damage_in_y; bool yc_limit; }; -__END_AKANTU__ +} // akantu #include "material_marigo_inline_impl.cc" #endif /* __AKANTU_MATERIAL_MARIGO_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh index f9c23eb9b..26fba660d 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh +++ b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh @@ -1,99 +1,99 @@ /** * @file material_marigo_non_local.hh * * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 15 2015 * * @brief Marigo non-local description * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_damage_non_local.hh" #include "material_marigo.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_MARIGO_NON_LOCAL_HH__ #define __AKANTU_MATERIAL_MARIGO_NON_LOCAL_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /** * Material Marigo * * parameters in the material files : */ template<UInt spatial_dimension> class MaterialMarigoNonLocal : public MaterialDamageNonLocal<spatial_dimension, MaterialMarigo<spatial_dimension> > { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef MaterialDamageNonLocal<spatial_dimension, MaterialMarigo<spatial_dimension> > MaterialMarigoNonLocalParent; MaterialMarigoNonLocal(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialMarigoNonLocal() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); protected: /// constitutive law void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); void computeNonLocalStress(ElementType type, GhostType ghost_type = _not_ghost); private: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Y, Y, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: InternalField<Real> Y; InternalField<Real> Ynl; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_marigo_non_local_inline_impl.cc" -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_MARIGO_NON_LOCAL_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local_inline_impl.cc b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local_inline_impl.cc index 1a0284831..317478899 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local_inline_impl.cc +++ b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local_inline_impl.cc @@ -1,105 +1,105 @@ /** * @file material_marigo_non_local_inline_impl.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 15 2015 * * @brief Marigo non-local inline function implementation * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #if defined(AKANTU_DEBUG_TOOLS) #include "aka_debug_tools.hh" #include <string> #endif -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialMarigoNonLocal<spatial_dimension>::MaterialMarigoNonLocal(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialMarigoNonLocalParent(model, id), Y("Y", *this), Ynl("Y non local", *this) { AKANTU_DEBUG_IN(); this->is_non_local = true; this->Y.initialize(1); this->Ynl.initialize(1); this->model->getNonLocalManager().registerNonLocalVariable(this->Y.getName(), Ynl.getName(), 1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialMarigoNonLocal<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialMarigoNonLocalParent::initMaterial(); this->model->getNonLocalManager().nonLocalVariableToNeighborhood(Ynl.getName(), this->name); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialMarigoNonLocal<spatial_dimension>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * dam = this->damage(el_type, ghost_type).storage(); Real * Yt = this->Y(el_type, ghost_type).storage(); Real * Ydq = this->Yd(el_type, ghost_type).storage(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); MaterialMarigo<spatial_dimension>::computeStressOnQuad(grad_u, sigma, *dam, *Yt, *Ydq); ++dam; ++Yt; ++Ydq; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialMarigoNonLocal<spatial_dimension>::computeNonLocalStress(ElementType type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * dam = this->damage(type, ghost_type).storage(); Real * Ydq = this->Yd(type, ghost_type).storage(); Real * Ynlt = this->Ynl(type, ghost_type).storage(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(type, ghost_type); this->computeDamageAndStressOnQuad(sigma, *dam, *Ynlt, *Ydq); ++dam; ++Ynlt; ++Ydq; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } diff --git a/src/model/solid_mechanics/materials/material_damage/material_mazars.cc b/src/model/solid_mechanics/materials/material_damage/material_mazars.cc index 0929b493e..46baaa4f8 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_mazars.cc +++ b/src/model/solid_mechanics/materials/material_damage/material_mazars.cc @@ -1,84 +1,84 @@ /** * @file material_mazars.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Aug 18 2015 * * @brief Specialization of the material class for the damage material * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_mazars.hh" #include "solid_mechanics_model.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialMazars<spatial_dimension>::MaterialMazars(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialDamage<spatial_dimension>(model, id), K0("K0", *this), damage_in_compute_stress(true) { AKANTU_DEBUG_IN(); this->registerParam("K0" , K0 , _pat_parsable, "K0"); this->registerParam("At" , At , Real(0.8 ), _pat_parsable, "At"); this->registerParam("Ac" , Ac , Real(1.4 ), _pat_parsable, "Ac"); this->registerParam("Bc" , Bc , Real(1900. ), _pat_parsable, "Bc"); this->registerParam("Bt" , Bt , Real(12000.), _pat_parsable, "Bt"); this->registerParam("beta", beta, Real(1.06 ), _pat_parsable, "beta"); this->K0.initialize(1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialMazars<spatial_dimension>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * dam = this->damage(el_type, ghost_type).storage(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Real Ehat = 0; computeStressOnQuad(grad_u, sigma, *dam, Ehat); ++dam; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialMazars); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_damage/material_mazars.hh b/src/model/solid_mechanics/materials/material_damage/material_mazars.hh index fe9da5555..3359bac63 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_mazars.hh +++ b/src/model/solid_mechanics/materials/material_damage/material_mazars.hh @@ -1,129 +1,129 @@ /** * @file material_mazars.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief Material Following the Mazars law for damage evolution * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_damage.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_MAZARS_HH__ #define __AKANTU_MATERIAL_MAZARS_HH__ -__BEGIN_AKANTU__ +namespace 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 */ template<UInt spatial_dimension> class MaterialMazars : public MaterialDamage<spatial_dimension> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialMazars(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialMazars() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); protected: /// constitutive law for a given quadrature point inline void computeStressOnQuad(const Matrix<Real> & grad_u, Matrix<Real> & sigma, Real & damage, Real & Ehat); inline void computeDamageAndStressOnQuad(const Matrix<Real> & grad_u, Matrix<Real> & sigma, Real & damage, Real & Ehat); inline void computeDamageOnQuad(const Real & epsilon_equ, const Matrix<Real> & sigma, const Vector<Real> & epsilon_princ, Real & dam); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// damage threshold RandomInternalField<Real> K0; ///parameter damage traction 1 Real At ; ///parameter damage traction 2 Real Bt ; ///parameter damage compression 1 Real Ac ; ///parameter damage compression 2 Real Bc ; ///parameter for shear Real beta ; /// specify the variable to average false = ehat, true = damage (only valid for non local version) bool damage_in_compute_stress; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_mazars_inline_impl.cc" -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_MAZARS_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc index 496c58e4f..911e6d4fd 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc +++ b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc @@ -1,148 +1,148 @@ /** * @file material_mazars_non_local.cc * * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 15 2015 * * @brief Specialization of the material class for the non-local mazars * material * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_mazars_non_local.hh" #include "solid_mechanics_model.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialMazarsNonLocal<spatial_dimension>::MaterialMazarsNonLocal( SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialMazars<spatial_dimension>(model, id), MaterialNonLocalParent(model, id), Ehat("epsilon_equ", *this) { AKANTU_DEBUG_IN(); this->is_non_local = true; this->Ehat.initialize(1); this->registerParam("average_on_damage", this->damage_in_compute_stress, false, _pat_parsable | _pat_modifiable, "Is D the non local variable"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMazarsNonLocal<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialMazars<spatial_dimension>::initMaterial(); MaterialNonLocalParent::initMaterial(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMazarsNonLocal<spatial_dimension>::computeStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * damage = this->damage(el_type, ghost_type).storage(); Real * epsilon_equ = this->Ehat(el_type, ghost_type).storage(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); MaterialMazars<spatial_dimension>::computeStressOnQuad(grad_u, sigma, *damage, *epsilon_equ); ++damage; ++epsilon_equ; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMazarsNonLocal<spatial_dimension>::computeNonLocalStresses( __attribute__((unused)) GhostType ghost_type) { AKANTU_DEBUG_IN(); InternalField<Real> nl_var("Non local variable", *this); nl_var.initialize(1); // if(this->damage_in_compute_stress) // this->weightedAvergageOnNeighbours(this->damage, nl_var, 1); // else // this->weightedAvergageOnNeighbours(this->Ehat, nl_var, 1); // Mesh::type_iterator it = // this->model->getFEEngine().getMesh().firstType(spatial_dimension, // ghost_type); // Mesh::type_iterator last_type = // this->model->getFEEngine().getMesh().lastType(spatial_dimension, // ghost_type); // for(; it != last_type; ++it) { // this->computeNonLocalStress(nl_var(*it, ghost_type), *it, ghost_type); // } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMazarsNonLocal<spatial_dimension>::computeNonLocalStress( Array<Real> & non_loc_var, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * damage; Real * epsilon_equ; if (this->damage_in_compute_stress) { damage = non_loc_var.storage(); epsilon_equ = this->Ehat(el_type, ghost_type).storage(); } else { damage = this->damage(el_type, ghost_type).storage(); epsilon_equ = non_loc_var.storage(); } MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); this->computeDamageAndStressOnQuad(grad_u, sigma, *damage, *epsilon_equ); ++damage; ++epsilon_equ; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMazarsNonLocal< spatial_dimension>::nonLocalVariableToNeighborhood() {} INSTANTIATE_MATERIAL(MaterialMazarsNonLocal); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.hh b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.hh index 1b2be905a..9e2539ef4 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.hh +++ b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.hh @@ -1,103 +1,103 @@ /** * @file material_mazars_non_local.hh * * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 08 2015 * * @brief Mazars non-local description * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_mazars.hh" #include "material_non_local.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_MAZARS_NON_LOCAL_HH__ #define __AKANTU_MATERIAL_MAZARS_NON_LOCAL_HH__ -__BEGIN_AKANTU__ +namespace akantu { /** * Material Mazars Non local * * parameters in the material files : */ template<UInt spatial_dimension> class MaterialMazarsNonLocal : public MaterialMazars<spatial_dimension>, public MaterialNonLocal<spatial_dimension> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef MaterialNonLocal<spatial_dimension> MaterialNonLocalParent; MaterialMazarsNonLocal(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialMazarsNonLocal() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// constitutive law void computeNonLocalStresses(GhostType ghost_type = _not_ghost); void computeNonLocalStress(Array<Real> & Ehatnl, ElementType el_type, GhostType ghost_type = _not_ghost); protected: /// associate the non-local variables of the material to their neighborhoods virtual void nonLocalVariableToNeighborhood(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// the ehat per quadrature points to perform the averaging InternalField<Real> Ehat; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "material_mazars_non_local_inline_impl.cc" -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_MAZARS_NON_LOCAL_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_elastic.cc b/src/model/solid_mechanics/materials/material_elastic.cc index 9d6979933..6cbacc296 100644 --- a/src/model/solid_mechanics/materials/material_elastic.cc +++ b/src/model/solid_mechanics/materials/material_elastic.cc @@ -1,255 +1,255 @@ /** * @file material_elastic.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 15 2015 * * @brief Specialization of the material class for the elastic material * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_elastic.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt dim> MaterialElastic<dim>::MaterialElastic(SolidMechanicsModel & model, const ID & id) : Material(model, id), Parent(model, id), was_stiffness_assembled(false) { AKANTU_DEBUG_IN(); this->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> MaterialElastic<dim>::MaterialElastic(SolidMechanicsModel & model, __attribute__((unused)) UInt a_dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id) : Material(model, dim, mesh, fe_engine, id), Parent(model, dim, mesh, fe_engine, id), was_stiffness_assembled(false) { AKANTU_DEBUG_IN(); this->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialElastic<dim>::initialize() { this->registerParam("lambda", lambda, _pat_readable, "First Lamé coefficient"); this->registerParam("mu", mu, _pat_readable, "Second Lamé coefficient"); this->registerParam("kapa", kpa, _pat_readable, "Bulk coefficient"); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialElastic<dim>::initMaterial() { AKANTU_DEBUG_IN(); Parent::initMaterial(); if (dim == 1) this->nu = 0.; this->updateInternalParameters(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialElastic<dim>::updateInternalParameters() { MaterialThermal<dim>::updateInternalParameters(); this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2 * this->nu)); this->mu = this->E / (2 * (1 + this->nu)); this->kpa = this->lambda + 2. / 3. * this->mu; this->was_stiffness_assembled = false; } /* -------------------------------------------------------------------------- */ template <> void MaterialElastic<2>::updateInternalParameters() { MaterialThermal<2>::updateInternalParameters(); this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2 * this->nu)); this->mu = this->E / (2 * (1 + this->nu)); if (this->plane_stress) this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - this->nu)); this->kpa = this->lambda + 2. / 3. * this->mu; this->was_stiffness_assembled = false; } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialElastic<spatial_dimension>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Parent::computeStress(el_type, ghost_type); Array<Real>::const_scalar_iterator sigma_th_it = this->sigma_th(el_type, ghost_type).begin(); if (!this->finite_deformation) { MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); const Real & sigma_th = *sigma_th_it; this->computeStressOnQuad(grad_u, sigma, sigma_th); ++sigma_th_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } else { /// finite gradus Matrix<Real> E(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); /// compute E this->template gradUToGreenStrain<spatial_dimension>(grad_u, E); const Real & sigma_th = *sigma_th_it; /// compute second Piola-Kirchhoff stress tensor this->computeStressOnQuad(E, sigma, sigma_th); ++sigma_th_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialElastic<spatial_dimension>::computeTangentModuli( const ElementType & el_type, Array<Real> & tangent_matrix, GhostType ghost_type) { AKANTU_DEBUG_IN(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); this->computeTangentModuliOnQuad(tangent); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; this->was_stiffness_assembled = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> Real MaterialElastic<spatial_dimension>::getPushWaveSpeed( const Element &) const { return sqrt((lambda + 2 * mu) / this->rho); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> Real MaterialElastic<spatial_dimension>::getShearWaveSpeed( const Element &) const { return sqrt(mu / this->rho); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialElastic<spatial_dimension>::computePotentialEnergy( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialThermal<spatial_dimension>::computePotentialEnergy(el_type, ghost_type); if (ghost_type != _not_ghost) return; auto epot = this->potential_energy(el_type, ghost_type).begin(); if (!this->finite_deformation) { MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); this->computePotentialEnergyOnQuad(grad_u, sigma, *epot); ++epot; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } else { Matrix<Real> E(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); this->template gradUToGreenStrain<spatial_dimension>(grad_u, E); this->computePotentialEnergyOnQuad(E, sigma, *epot); ++epot; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialElastic<spatial_dimension>::computePotentialEnergyByElement( ElementType type, UInt index, Vector<Real> & epot_on_quad_points) { auto gradu_it = this->gradu(type).begin(spatial_dimension, spatial_dimension); auto gradu_end = this->gradu(type).begin(spatial_dimension, spatial_dimension); auto stress_it = this->stress(type).begin(spatial_dimension, spatial_dimension); if (this->finite_deformation) stress_it = this->piola_kirchhoff_2(type).begin(spatial_dimension, spatial_dimension); UInt nb_quadrature_points = this->model->getFEEngine().getNbIntegrationPoints(type); gradu_it += index * nb_quadrature_points; gradu_end += (index + 1) * nb_quadrature_points; stress_it += index * nb_quadrature_points; Real * epot_quad = epot_on_quad_points.storage(); Matrix<Real> grad_u(spatial_dimension, spatial_dimension); for (; gradu_it != gradu_end; ++gradu_it, ++stress_it, ++epot_quad) { if (this->finite_deformation) this->template gradUToGreenStrain<spatial_dimension>(*gradu_it, grad_u); else grad_u.copy(*gradu_it); this->computePotentialEnergyOnQuad(grad_u, *stress_it, *epot_quad); } } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialElastic); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc index 617bb1e6b..7274d8521 100644 --- a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc +++ b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc @@ -1,313 +1,313 @@ /** * @file material_elastic_linear_anisotropic.cc * * @author Till Junge <till.junge@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Sep 25 2013 * @date last modification: Thu Oct 15 2015 * * @brief Anisotropic elastic material * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "material_elastic_linear_anisotropic.hh" #include "solid_mechanics_model.hh" #include <algorithm> #include <sstream> -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt dim> MaterialElasticLinearAnisotropic<dim>::MaterialElasticLinearAnisotropic( SolidMechanicsModel & model, const ID & id, bool symmetric) : Material(model, id), rot_mat(dim, dim), Cprime(dim * dim, dim * dim), C(voigt_h::size, voigt_h::size), eigC(voigt_h::size), symmetric(symmetric), alpha(0), was_stiffness_assembled(false) { AKANTU_DEBUG_IN(); this->dir_vecs.push_back(new Vector<Real>(dim)); (*this->dir_vecs.back())[0] = 1.; this->registerParam("n1", *(this->dir_vecs.back()), _pat_parsmod, "Direction of main material axis"); this->dir_vecs.push_back(new Vector<Real>(dim)); (*this->dir_vecs.back())[1] = 1.; this->registerParam("n2", *(this->dir_vecs.back()), _pat_parsmod, "Direction of secondary material axis"); if (dim > 2) { this->dir_vecs.push_back(new Vector<Real>(dim)); (*this->dir_vecs.back())[2] = 1.; this->registerParam("n3", *(this->dir_vecs.back()), _pat_parsmod, "Direction of tertiary material axis"); } for (UInt i = 0; i < voigt_h::size; ++i) { UInt start = 0; if (this->symmetric) { start = i; } for (UInt j = start; j < voigt_h::size; ++j) { std::stringstream param("C"); param << "C" << i + 1 << j + 1; this->registerParam(param.str(), this->Cprime(i, j), Real(0.), _pat_parsmod, "Coefficient " + param.str()); } } this->registerParam("alpha", this->alpha, _pat_parsmod, "Proportion of viscous stress"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> MaterialElasticLinearAnisotropic<dim>::~MaterialElasticLinearAnisotropic() { for (UInt i = 0; i < dim; ++i) { delete this->dir_vecs[i]; } } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialElasticLinearAnisotropic<dim>::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); updateInternalParameters(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialElasticLinearAnisotropic<dim>::updateInternalParameters() { Material::updateInternalParameters(); if (this->symmetric) { for (UInt i = 0; i < voigt_h::size; ++i) { for (UInt j = i + 1; j < voigt_h::size; ++j) { this->Cprime(j, i) = this->Cprime(i, j); } } } this->rotateCprime(); this->C.eig(this->eigC); this->was_stiffness_assembled = false; } /* -------------------------------------------------------------------------- */ template <UInt Dim> void MaterialElasticLinearAnisotropic<Dim>::rotateCprime() { // start by filling the empty parts fo Cprime UInt diff = Dim * Dim - voigt_h::size; for (UInt i = voigt_h::size; i < Dim * Dim; ++i) { for (UInt j = 0; j < Dim * Dim; ++j) { this->Cprime(i, j) = this->Cprime(i - diff, j); } } for (UInt i = 0; i < Dim * Dim; ++i) { for (UInt j = voigt_h::size; j < Dim * Dim; ++j) { this->Cprime(i, j) = this->Cprime(i, j - diff); } } // construction of rotator tensor // normalise rotation matrix for (UInt j = 0; j < Dim; ++j) { Vector<Real> rot_vec = this->rot_mat(j); rot_vec = *this->dir_vecs[j]; rot_vec.normalize(); } // make sure the vectors form a right-handed base Vector<Real> test_axis(3); Vector<Real> v1(3), v2(3), v3(3); if (Dim == 2) { for (UInt i = 0; i < Dim; ++i) { v1[i] = this->rot_mat(0, i); v2[i] = this->rot_mat(1, i); v3[i] = 0.; } v3[2] = 1.; v1[2] = 0.; v2[2] = 0.; } else if (Dim == 3) { v1 = this->rot_mat(0); v2 = this->rot_mat(1); v3 = this->rot_mat(2); } test_axis.crossProduct(v1, v2); test_axis -= v3; if (test_axis.norm() > 8 * std::numeric_limits<Real>::epsilon()) { AKANTU_DEBUG_ERROR("The axis vectors do not form a right-handed coordinate " << "system. I. e., ||n1 x n2 - n3|| should be zero, but " << "it is " << test_axis.norm() << "."); } // create the rotator and the reverse rotator Matrix<Real> rotator(Dim * Dim, Dim * Dim); Matrix<Real> revrotor(Dim * Dim, Dim * Dim); for (UInt i = 0; i < Dim; ++i) { for (UInt j = 0; j < Dim; ++j) { for (UInt k = 0; k < Dim; ++k) { for (UInt l = 0; l < Dim; ++l) { UInt I = voigt_h::mat[i][j]; UInt J = voigt_h::mat[k][l]; rotator(I, J) = this->rot_mat(k, i) * this->rot_mat(l, j); revrotor(I, J) = this->rot_mat(i, k) * this->rot_mat(j, l); } } } } // create the full rotated matrix Matrix<Real> Cfull(Dim * Dim, Dim * Dim); Cfull = rotator * Cprime * revrotor; for (UInt i = 0; i < voigt_h::size; ++i) { for (UInt j = 0; j < voigt_h::size; ++j) { this->C(i, j) = Cfull(i, j); } } } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialElasticLinearAnisotropic<dim>::computeStress( ElementType el_type, GhostType ghost_type) { // Wikipedia convention: // 2*eps_ij (i!=j) = voigt_eps_I // http://en.wikipedia.org/wiki/Voigt_notation AKANTU_DEBUG_IN(); Array<Real>::iterator<Matrix<Real>> gradu_it = this->gradu(el_type, ghost_type).begin(dim, dim); Array<Real>::iterator<Matrix<Real>> gradu_end = this->gradu(el_type, ghost_type).end(dim, dim); UInt nb_quad_pts = gradu_end - gradu_it; // create array for strains and stresses of all dof of all gauss points // for efficient computation of stress Matrix<Real> voigt_strains(voigt_h::size, nb_quad_pts); Matrix<Real> voigt_stresses(voigt_h::size, nb_quad_pts); // copy strains Matrix<Real> strain(dim, dim); for (UInt q = 0; gradu_it != gradu_end; ++gradu_it, ++q) { Matrix<Real> & grad_u = *gradu_it; for (UInt I = 0; I < voigt_h::size; ++I) { Real voigt_factor = voigt_h::factors[I]; UInt i = voigt_h::vec[I][0]; UInt j = voigt_h::vec[I][1]; voigt_strains(I, q) = voigt_factor * (grad_u(i, j) + grad_u(j, i)) / 2.; } } // compute the strain rate proportional part if needed // bool viscous = this->alpha == 0.; // only works if default value bool viscous = false; if (viscous) { Array<Real> strain_rate(0, dim * dim, "strain_rate"); Array<Real> & velocity = this->model->getVelocity(); const Array<UInt> & elem_filter = this->element_filter(el_type, ghost_type); this->model->getFEEngine().gradientOnIntegrationPoints( velocity, strain_rate, dim, el_type, ghost_type, elem_filter); Array<Real>::matrix_iterator gradu_dot_it = strain_rate.begin(dim, dim); Array<Real>::matrix_iterator gradu_dot_end = strain_rate.end(dim, dim); Matrix<Real> strain_dot(dim, dim); for (UInt q = 0; gradu_dot_it != gradu_dot_end; ++gradu_dot_it, ++q) { Matrix<Real> & grad_u_dot = *gradu_dot_it; for (UInt I = 0; I < voigt_h::size; ++I) { Real voigt_factor = voigt_h::factors[I]; UInt i = voigt_h::vec[I][0]; UInt j = voigt_h::vec[I][1]; voigt_strains(I, q) = this->alpha * voigt_factor * (grad_u_dot(i, j) + grad_u_dot(j, i)) / 2.; } } } // compute stresses voigt_stresses = this->C * voigt_strains; // copy stresses back Array<Real>::iterator<Matrix<Real>> stress_it = this->stress(el_type, ghost_type).begin(dim, dim); Array<Real>::iterator<Matrix<Real>> stress_end = this->stress(el_type, ghost_type).end(dim, dim); for (UInt q = 0; stress_it != stress_end; ++stress_it, ++q) { Matrix<Real> & stress = *stress_it; for (UInt I = 0; I < voigt_h::size; ++I) { UInt i = voigt_h::vec[I][0]; UInt j = voigt_h::vec[I][1]; stress(i, j) = stress(j, i) = voigt_stresses(I, q); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialElasticLinearAnisotropic<dim>::computeTangentModuli( const ElementType & el_type, Array<Real> & tangent_matrix, GhostType ghost_type) { AKANTU_DEBUG_IN(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); tangent.copy(this->C); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; this->was_stiffness_assembled = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> Real MaterialElasticLinearAnisotropic<dim>::getCelerity( __attribute__((unused)) const Element & element) const { return std::sqrt(this->eigC(0) / rho); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialElasticLinearAnisotropic); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh index 2b1b854ac..24f87cef8 100644 --- a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh +++ b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh @@ -1,128 +1,128 @@ /** * @file material_elastic_linear_anisotropic.hh * * @author Till Junge <till.junge@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Aug 18 2015 * * @brief Orthotropic elastic material * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" #include "material_elastic.hh" #include <vector> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_ELASTIC_LINEAR_ANISOTROPIC_HH__ #define __AKANTU_MATERIAL_ELASTIC_LINEAR_ANISOTROPIC_HH__ -__BEGIN_AKANTU__ +namespace akantu { /** * General linear anisotropic elastic material * The only constraint on the elastic tensor is that it can be represented * as a symmetric 6x6 matrix (3D) or 3x3 (2D). * * parameters in the material files : * - rho : density (default: 0) * - C_ij : entry on the stiffness */ template <UInt Dim> class MaterialElasticLinearAnisotropic : public virtual Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialElasticLinearAnisotropic(SolidMechanicsModel & model, const ID & id = "", bool symmetric = true); ~MaterialElasticLinearAnisotropic(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void initMaterial(); /// 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 computeTangentModuli(const ElementType & el_type, Array<Real> & tangent_matrix, GhostType ghost_type = _not_ghost); virtual void updateInternalParameters(); virtual bool hasStiffnessMatrixChanged() { return (! was_stiffness_assembled); } protected: // compute C from Cprime void rotateCprime(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// compute max wave celerity virtual Real getCelerity(const Element & element) const; AKANTU_GET_MACRO(VoigtStiffness, C, Matrix<Real>); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: typedef VoigtHelper<Dim> voigt_h; /// direction matrix and vectors std::vector<Vector<Real> *> dir_vecs; Matrix<Real> rot_mat; /// Elastic stiffness tensor in material frame and full vectorised notation Matrix<Real> Cprime; /// Elastic stiffness tensor in voigt notation Matrix<Real> C; /// eigenvalues of stiffness tensor Vector<Real> eigC; bool symmetric; /// viscous proportion Real alpha; /// defines if the stiffness was computed bool was_stiffness_assembled; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_ELASTIC_LINEAR_ANISOTROPIC_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc b/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc index 5a1158eda..f5c0d8588 100644 --- a/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc +++ b/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc @@ -1,213 +1,213 @@ /** * @file material_elastic_orthotropic.cc * * @author Till Junge <till.junge@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 15 2015 * * @brief Orthotropic elastic material * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "material_elastic_orthotropic.hh" #include "solid_mechanics_model.hh" #include <algorithm> -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt Dim> MaterialElasticOrthotropic<Dim>::MaterialElasticOrthotropic(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialElasticLinearAnisotropic<Dim>(model, id) { AKANTU_DEBUG_IN(); this->registerParam("E1", E1 , Real(0.), _pat_parsmod, "Young's modulus (n1)"); this->registerParam("E2", E2 , Real(0.), _pat_parsmod, "Young's modulus (n2)"); this->registerParam("nu12", nu12, Real(0.), _pat_parsmod, "Poisson's ratio (12)"); this->registerParam("G12", G12 , Real(0.), _pat_parsmod, "Shear modulus (12)"); if (Dim > 2) { this->registerParam("E3" , E3 , Real(0.), _pat_parsmod, "Young's modulus (n3)"); this->registerParam("nu13", nu13, Real(0.), _pat_parsmod, "Poisson's ratio (13)"); this->registerParam("nu23", nu23, Real(0.), _pat_parsmod, "Poisson's ratio (23)"); this->registerParam("G13" , G13 , Real(0.), _pat_parsmod, "Shear modulus (13)"); this->registerParam("G23" , G23 , Real(0.), _pat_parsmod, "Shear modulus (23)"); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt Dim> MaterialElasticOrthotropic<Dim>::~MaterialElasticOrthotropic() { } /* -------------------------------------------------------------------------- */ template<UInt Dim> void MaterialElasticOrthotropic<Dim>::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); updateInternalParameters(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline Real vector_norm(Vector<Real> & vec) { Real norm = 0; for (UInt i = 0 ; i < vec.size() ; ++i) { norm += vec(i)*vec(i); } return std::sqrt(norm); } /* -------------------------------------------------------------------------- */ template<UInt Dim> void MaterialElasticOrthotropic<Dim>::updateInternalParameters() { /* 1) construction of temporary material frame stiffness tensor------------ */ // http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13 Real nu21 = nu12 * E2 / E1; Real nu31 = nu13 * E3 / E1; Real nu32 = nu23 * E3 / E2; // Full (i.e. dim^2 by dim^2) stiffness tensor in material frame if (Dim == 1) { AKANTU_DEBUG_ERROR("Dimensions 1 not implemented: makes no sense to have orthotropy for 1D"); } Real Gamma; if (Dim == 3) Gamma = 1/(1 - nu12 * nu21 - nu23 * nu32 - nu31 * nu13 - 2 * nu21 * nu32 * nu13); if (Dim == 2) Gamma = 1/(1 - nu12 * nu21); // Lamé's first parameters this->Cprime(0, 0) = E1 * (1 - nu23 * nu32) * Gamma; this->Cprime(1, 1) = E2 * (1 - nu13 * nu31) * Gamma; if (Dim == 3) this->Cprime(2, 2) = E3 * (1 - nu12 * nu21) * Gamma; // normalised poisson's ratio's this->Cprime(1, 0) = this->Cprime(0, 1) = E1 * (nu21 + nu31 * nu23) * Gamma; if (Dim == 3) { this->Cprime(2, 0) = this->Cprime(0, 2) = E1 * (nu31 + nu21 * nu32) * Gamma; this->Cprime(2, 1) = this->Cprime(1, 2) = E2 * (nu32 + nu12 * nu31) * Gamma; } // Lamé's second parameters (shear moduli) if (Dim == 3) { this->Cprime(3, 3) = G23; this->Cprime(4, 4) = G13; this->Cprime(5, 5) = G12; } else this->Cprime(2, 2) = G12; /* 1) rotation of C into the global frame */ this->rotateCprime(); this->C.eig(this->eigC); } /* -------------------------------------------------------------------------- */ template<UInt dim> inline void MaterialElasticOrthotropic<dim>::computePotentialEnergyOnQuad(const Matrix<Real> & grad_u, const Matrix<Real> & sigma, Real & epot) { epot = .5 * sigma.doubleDot(grad_u); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialElasticOrthotropic<spatial_dimension>::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Material::computePotentialEnergy(el_type, ghost_type); AKANTU_DEBUG_ASSERT(!this->finite_deformation,"finite deformation not possible in material orthotropic (TO BE IMPLEMENTED)"); if(ghost_type != _not_ghost) return; Array<Real>::scalar_iterator epot = this->potential_energy(el_type, ghost_type).begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); computePotentialEnergyOnQuad(grad_u, sigma, *epot); ++epot; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialElasticOrthotropic<spatial_dimension>::computePotentialEnergyByElement(ElementType type, UInt index, Vector<Real> & epot_on_quad_points) { AKANTU_DEBUG_ASSERT(!this->finite_deformation,"finite deformation not possible in material orthotropic (TO BE IMPLEMENTED)"); Array<Real>::matrix_iterator gradu_it = this->gradu(type).begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator gradu_end = this->gradu(type).begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator stress_it = this->stress(type).begin(spatial_dimension, spatial_dimension); UInt nb_quadrature_points = this->model->getFEEngine().getNbIntegrationPoints(type); gradu_it += index*nb_quadrature_points; gradu_end += (index+1)*nb_quadrature_points; stress_it += index*nb_quadrature_points; Real * epot_quad = epot_on_quad_points.storage(); Matrix<Real> grad_u(spatial_dimension, spatial_dimension); for(;gradu_it != gradu_end; ++gradu_it, ++stress_it, ++epot_quad) { grad_u.copy(*gradu_it); computePotentialEnergyOnQuad(grad_u, *stress_it, *epot_quad); } } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialElasticOrthotropic); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_elastic_orthotropic.hh b/src/model/solid_mechanics/materials/material_elastic_orthotropic.hh index 53922cd66..e0a6a4c1d 100644 --- a/src/model/solid_mechanics/materials/material_elastic_orthotropic.hh +++ b/src/model/solid_mechanics/materials/material_elastic_orthotropic.hh @@ -1,149 +1,149 @@ /** * @file material_elastic_orthotropic.hh * * @author Till Junge <till.junge@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief Orthotropic elastic material * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_elastic_linear_anisotropic.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_ELASTIC_ORTHOTROPIC_HH__ #define __AKANTU_MATERIAL_ELASTIC_ORTHOTROPIC_HH__ -__BEGIN_AKANTU__ +namespace akantu { /** * Orthotropic elastic material * * parameters in the material files : * - n1 : direction of x-axis in material base, normalisation not necessary (default: {1, 0, 0}) * - n2 : direction of y-axis in material base, normalisation not necessary (default: {0, 1, 0}) * - n3 : direction of z-axis in material base, normalisation not necessary (default: {0, 0, 1}) * - rho : density (default: 0) * - E1 : Young's modulus along n1 (default: 0) * - E2 : Young's modulus along n2 (default: 0) * - E3 : Young's modulus along n3 (default: 0) * - nu12 : Poisson's ratio along 12 (default: 0) * - nu13 : Poisson's ratio along 13 (default: 0) * - nu23 : Poisson's ratio along 23 (default: 0) * - G12 : Shear modulus along 12 (default: 0) * - G13 : Shear modulus along 13 (default: 0) * - G23 : Shear modulus along 23 (default: 0) */ template<UInt Dim> class MaterialElasticOrthotropic : public MaterialElasticLinearAnisotropic<Dim> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialElasticOrthotropic(SolidMechanicsModel & model, const ID & id = ""); ~MaterialElasticOrthotropic(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void initMaterial(); virtual void updateInternalParameters(); /// compute the elastic potential energy virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); virtual void computePotentialEnergyByElement(ElementType type, UInt index, Vector<Real> & epot_on_quad_points); protected: inline void computePotentialEnergyOnQuad(const Matrix<Real> & grad_u, const Matrix<Real> & sigma, Real & epot); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(E1, E1, Real); AKANTU_GET_MACRO(E2, E2, Real); AKANTU_GET_MACRO(E3, E3, Real); AKANTU_GET_MACRO(Nu12, nu12, Real); AKANTU_GET_MACRO(Nu13, nu13, Real); AKANTU_GET_MACRO(Nu23, nu23, Real); AKANTU_GET_MACRO(G12, G12, Real); AKANTU_GET_MACRO(G13, G13, Real); AKANTU_GET_MACRO(G23, G23, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// the n1 young modulus Real E1; /// the n2 young modulus Real E2; /// the n3 young modulus Real E3; /// 12 Poisson coefficient Real nu12; /// 13 Poisson coefficient Real nu13; /// 23 Poisson coefficient Real nu23; /// 12 shear modulus Real G12; /// 13 shear modulus Real G13; /// 23 shear modulus Real G23; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_ELASTIC_ORTHOTROPIC_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_embedded/embedded_internal_field.hh b/src/model/solid_mechanics/materials/material_embedded/embedded_internal_field.hh index b40e84454..2d139f5b7 100644 --- a/src/model/solid_mechanics/materials/material_embedded/embedded_internal_field.hh +++ b/src/model/solid_mechanics/materials/material_embedded/embedded_internal_field.hh @@ -1,83 +1,83 @@ /** * @file embedded_internal_field.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Jun 30 2015 * * @brief Embedded Material internal properties * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "internal_field.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_EMBEDDED_INTERNAL_FIELD_HH__ #define __AKANTU_EMBEDDED_INTERNAL_FIELD_HH__ -__BEGIN_AKANTU__ +namespace akantu { class Material; class FEEngine; /// This class is used for MaterialReinforcement internal fields template<typename T> class EmbeddedInternalField : public InternalField<T> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: /// Constructor EmbeddedInternalField(const ID & id, Material & material): InternalField<T>(id, material, material.getModel().getFEEngine("EmbeddedInterfaceFEEngine"), material.getElementFilter()) { this->spatial_dimension = 1; } /// Copy constructor EmbeddedInternalField(const ID & id, const EmbeddedInternalField & other): InternalField<T>(id, other) { this->spatial_dimension = 1; } void operator=(const EmbeddedInternalField & other) { InternalField<T>::operator=(other); this->spatial_dimension = 1; } }; /// Method used to initialise the embedded internal fields from material file template<> inline void ParsableParamTyped< EmbeddedInternalField<Real> >::parseParam(const ParserParameter & in_param) { ParsableParam::parseParam(in_param); Real r = in_param; param.setDefaultValue(r); } -__END_AKANTU__ +} // akantu #endif // __AKANTU_EMBEDDED_INTERNAL_FIELD_HH__ diff --git a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.cc b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.cc index 96f790fa6..304c97685 100644 --- a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.cc +++ b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.cc @@ -1,784 +1,784 @@ /** * @file material_reinforcement.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Wed Mar 25 2015 * @date last modification: Tue Dec 08 2015 * * @brief Reinforcement material * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_voigthelper.hh" #include "material_reinforcement.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt dim> MaterialReinforcement<dim>::MaterialReinforcement(SolidMechanicsModel & model, UInt spatial_dimension, const Mesh & mesh, FEEngine & fe_engine, const ID & id) : Material(model, dim, mesh, fe_engine, id), // /!\ dim, not spatial_dimension ! model(NULL), stress_embedded("stress_embedded", *this, 1, fe_engine, this->element_filter), gradu_embedded("gradu_embedded", *this, 1, fe_engine, this->element_filter), directing_cosines("directing_cosines", *this, 1, fe_engine, this->element_filter), pre_stress("pre_stress", *this, 1, fe_engine, this->element_filter), area(1.0), shape_derivatives() { AKANTU_DEBUG_IN(); this->initialize(model); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialReinforcement<dim>::initialize(SolidMechanicsModel & a_model) { AKANTU_DEBUG_IN(); this->model = dynamic_cast<EmbeddedInterfaceModel *>(&a_model); AKANTU_DEBUG_ASSERT(this->model != NULL, "MaterialReinforcement needs an EmbeddedInterfaceModel"); this->registerParam("area", area, _pat_parsable | _pat_modifiable, "Reinforcement cross-sectional area"); this->registerParam("pre_stress", pre_stress, _pat_parsable | _pat_modifiable, "Uniform pre-stress"); this->unregisterInternal(this->stress); // Fool the AvgHomogenizingFunctor // stress.initialize(dim * dim); // Reallocate the element filter this->element_filter.free(); this->model->getInterfaceMesh().initElementTypeMapArray(this->element_filter, 1, 1, false, _ek_regular); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> MaterialReinforcement<dim>::~MaterialReinforcement() { AKANTU_DEBUG_IN(); ElementTypeMap<ElementTypeMapArray<Real> *>::type_iterator it = shape_derivatives.firstType(), end = shape_derivatives.lastType(); for (; it != end; ++it) { delete shape_derivatives(*it, _not_ghost); delete shape_derivatives(*it, _ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialReinforcement<dim>::initMaterial() { Material::initMaterial(); stress_embedded.initialize(dim * dim); gradu_embedded.initialize(dim * dim); pre_stress.initialize(1); /// We initialise the stuff that is not going to change during the simulation this->allocBackgroundShapeDerivatives(); this->initBackgroundShapeDerivatives(); this->initDirectingCosines(); } /* -------------------------------------------------------------------------- */ /** * Background shape derivatives need to be stored per background element * types but also per embedded element type, which is why they are stored * in an ElementTypeMap<ElementTypeMapArray<Real> *>. The outer ElementTypeMap * refers to the embedded types, and the inner refers to the background types. */ template <UInt dim> void MaterialReinforcement<dim>::allocBackgroundShapeDerivatives() { AKANTU_DEBUG_IN(); Mesh & interface_mesh = model->getInterfaceMesh(); Mesh & mesh = model->getMesh(); ghost_type_t::iterator int_ghost_it = ghost_type_t::begin(); // Loop over interface ghosts for (; int_ghost_it != ghost_type_t::end(); ++int_ghost_it) { Mesh::type_iterator interface_type_it = interface_mesh.firstType(1, *int_ghost_it); Mesh::type_iterator interface_type_end = interface_mesh.lastType(1, *int_ghost_it); // Loop over interface types for (; interface_type_it != interface_type_end; ++interface_type_it) { Mesh::type_iterator background_type_it = mesh.firstType(dim, *int_ghost_it); Mesh::type_iterator background_type_end = mesh.lastType(dim, *int_ghost_it); // Loop over background types for (; background_type_it != background_type_end ; ++background_type_it) { const ElementType & int_type = *interface_type_it; const ElementType & back_type = *background_type_it; const GhostType & int_ghost = *int_ghost_it; std::string shaped_id = "embedded_shape_derivatives"; if (int_ghost == _ghost) shaped_id += ":ghost"; ElementTypeMapArray<Real> * shaped_etma = new ElementTypeMapArray<Real>(shaped_id, this->name); UInt nb_points = Mesh::getNbNodesPerElement(back_type); UInt nb_quad_points = model->getFEEngine("EmbeddedInterfaceFEEngine").getNbIntegrationPoints(int_type); UInt nb_elements = element_filter(int_type, int_ghost).getSize(); // Alloc the background ElementTypeMapArray shaped_etma->alloc(nb_elements * nb_quad_points, dim * nb_points, back_type); // Insert the background ElementTypeMapArray in the interface // ElementTypeMap shape_derivatives(shaped_etma, int_type, int_ghost); } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialReinforcement<dim>::initBackgroundShapeDerivatives() { AKANTU_DEBUG_IN(); Mesh & mesh = model->getMesh(); Mesh::type_iterator type_it = mesh.firstType(dim, _not_ghost); Mesh::type_iterator type_end = mesh.lastType(dim, _not_ghost); for (; type_it != type_end; ++type_it) { computeBackgroundShapeDerivatives(*type_it, _not_ghost); // computeBackgroundShapeDerivatives(*type_it, _ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialReinforcement<dim>::initDirectingCosines() { AKANTU_DEBUG_IN(); Mesh & mesh = model->getInterfaceMesh(); Mesh::type_iterator type_it = mesh.firstType(1, _not_ghost); Mesh::type_iterator type_end = mesh.lastType(1, _not_ghost); const UInt voigt_size = getTangentStiffnessVoigtSize(dim); directing_cosines.initialize(voigt_size * voigt_size); for (; type_it != type_end; ++type_it) { computeDirectingCosines(*type_it, _not_ghost); // computeDirectingCosines(*type_it, _ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialReinforcement<dim>::assembleStiffnessMatrix(GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh & interface_mesh = model->getInterfaceMesh(); Mesh::type_iterator type_it = interface_mesh.firstType(1, _not_ghost); Mesh::type_iterator type_end = interface_mesh.lastType(1, _not_ghost); for (; type_it != type_end; ++type_it) { assembleStiffnessMatrix(*type_it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialReinforcement<dim>::assembleInternalForces(GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh & interface_mesh = model->getInterfaceMesh(); Mesh::type_iterator type_it = interface_mesh.firstType(1, _not_ghost); Mesh::type_iterator type_end = interface_mesh.lastType(1, _not_ghost); for (; type_it != type_end; ++type_it) { this->assembleInternalForces(*type_it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialReinforcement<dim>::computeGradU(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<UInt> & elem_filter = element_filter(type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_quad_points = model->getFEEngine("EmbeddedInterfaceFEEngine") .getNbIntegrationPoints(type); Array<Real> & gradu_vec = gradu_embedded(type, ghost_type); Mesh::type_iterator back_it = model->getMesh().firstType(dim, ghost_type); Mesh::type_iterator back_end = model->getMesh().lastType(dim, ghost_type); for (; back_it != back_end; ++back_it) { UInt nodes_per_background_e = Mesh::getNbNodesPerElement(*back_it); Array<Real> & shapesd = shape_derivatives(type, ghost_type)->operator()(*back_it, ghost_type); Array<UInt> * background_filter = new Array<UInt>(nb_element, 1, "background_filter"); filterInterfaceBackgroundElements(*background_filter, *back_it, type, ghost_type); Array<Real> * disp_per_element = new Array<Real>(0, dim * nodes_per_background_e, "disp_elem"); FEEngine::extractNodalToElementField(model->getMesh(), model->getDisplacement(), *disp_per_element, *back_it, ghost_type, *background_filter); Array<Real>::matrix_iterator disp_it = disp_per_element->begin(dim, nodes_per_background_e); Array<Real>::matrix_iterator disp_end = disp_per_element->end(dim, nodes_per_background_e); Array<Real>::matrix_iterator shapes_it = shapesd.begin(dim, nodes_per_background_e); Array<Real>::matrix_iterator grad_u_it = gradu_vec.begin(dim, dim); for (; disp_it != disp_end; ++disp_it) { for (UInt i = 0; i < nb_quad_points; i++, ++shapes_it, ++grad_u_it) { Matrix<Real> & B = *shapes_it; Matrix<Real> & du = *grad_u_it; Matrix<Real> & u = *disp_it; du.mul<false, true>(u, B); } } delete background_filter; delete disp_per_element; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialReinforcement<dim>::computeAllStresses(GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh::type_iterator it = model->getInterfaceMesh().firstType(); Mesh::type_iterator last_type = model->getInterfaceMesh().lastType(); for (; it != last_type; ++it) { computeGradU(*it, ghost_type); computeStress(*it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialReinforcement<dim>::assembleInternalForces( const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh & mesh = model->getMesh(); Mesh::type_iterator type_it = mesh.firstType(dim, ghost_type); Mesh::type_iterator type_end = mesh.lastType(dim, ghost_type); for (; type_it != type_end; ++type_it) { assembleInternalForcesInterface(type, *type_it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Computes and assemble the residual. Residual in reinforcement is computed as * : * \f[ * \vec{r} = A_s \int_S{\mathbf{B}^T\mathbf{C}^T \vec{\sigma_s}\,\mathrm{d}s} * \f] */ template <UInt dim> void MaterialReinforcement<dim>::assembleInternalForcesInterface( const ElementType & interface_type, const ElementType & background_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt voigt_size = getTangentStiffnessVoigtSize(dim); Array<Real> & residual = const_cast<Array<Real> &>(model->getResidual()); FEEngine & interface_engine = model->getFEEngine("EmbeddedInterfaceFEEngine"); FEEngine & background_engine = model->getFEEngine(); Array<UInt> & elem_filter = element_filter(interface_type, ghost_type); UInt nodes_per_background_e = Mesh::getNbNodesPerElement(background_type); UInt nb_quadrature_points = interface_engine.getNbIntegrationPoints(interface_type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt back_dof = dim * nodes_per_background_e; Array<Real> & shapesd = shape_derivatives(interface_type, ghost_type) -> operator()(background_type, ghost_type); Array<Real> * integrant = new Array<Real>(nb_quadrature_points * nb_element, back_dof, "integrant"); Array<Real>::vector_iterator integrant_it = integrant->begin(back_dof); Array<Real>::vector_iterator integrant_end = integrant->end(back_dof); Array<Real>::matrix_iterator B_it = shapesd.begin(dim, nodes_per_background_e); Array<Real>::matrix_iterator C_it = directing_cosines(interface_type, ghost_type) .begin(voigt_size, voigt_size); Array<Real>::matrix_iterator sigma_it = stress_embedded(interface_type, ghost_type).begin(dim, dim); Vector<Real> sigma(voigt_size); Matrix<Real> Bvoigt(voigt_size, back_dof); Vector<Real> Ct_sigma(voigt_size); for (; integrant_it != integrant_end ; ++integrant_it, ++B_it, ++C_it, ++sigma_it) { VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(*B_it, Bvoigt, nodes_per_background_e); Matrix<Real> & C = *C_it; Vector<Real> & BtCt_sigma = *integrant_it; stressTensorToVoigtVector(*sigma_it, sigma); Ct_sigma.mul<true>(C, sigma); BtCt_sigma.mul<true>(Bvoigt, Ct_sigma); BtCt_sigma *= area; } Array<Real> * residual_interface = new Array<Real>(nb_element, back_dof, "residual_interface"); interface_engine.integrate(*integrant, *residual_interface, back_dof, interface_type, ghost_type, elem_filter); delete integrant; Array<UInt> * background_filter = new Array<UInt>(nb_element, 1, "background_filter"); filterInterfaceBackgroundElements(*background_filter, background_type, interface_type, ghost_type); background_engine.assembleArray( *residual_interface, residual, model->getDOFSynchronizer().getLocalDOFEquationNumbers(), dim, background_type, ghost_type, *background_filter, -1.0); delete residual_interface; delete background_filter; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialReinforcement<dim>::filterInterfaceBackgroundElements( Array<UInt> & filter, const ElementType & type, const ElementType & interface_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); filter.resize(0); filter.clear(); Array<Element> & elements = model->getInterfaceAssociatedElements(interface_type, ghost_type); Array<UInt> & elem_filter = element_filter(interface_type, ghost_type); Array<UInt>::scalar_iterator filter_it = elem_filter.begin(), filter_end = elem_filter.end(); for (; filter_it != filter_end; ++filter_it) { Element & elem = elements(*filter_it); if (elem.type == type) filter.push_back(elem.element); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialReinforcement<dim>::computeDirectingCosines( const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh & interface_mesh = this->model->getInterfaceMesh(); const UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); const UInt steel_dof = dim * nb_nodes_per_element; const UInt voigt_size = getTangentStiffnessVoigtSize(dim); const UInt nb_quad_points = model->getFEEngine("EmbeddedInterfaceFEEngine") .getNbIntegrationPoints(type, ghost_type); Array<Real> node_coordinates(this->element_filter(type, ghost_type).getSize(), steel_dof); this->model->getFEEngine().template extractNodalToElementField<Real>(interface_mesh, interface_mesh.getNodes(), node_coordinates, type, ghost_type, this->element_filter(type, ghost_type)); Array<Real>::matrix_iterator directing_cosines_it = directing_cosines(type, ghost_type).begin(voigt_size, voigt_size); Array<Real>::matrix_iterator node_coordinates_it = node_coordinates.begin(dim, nb_nodes_per_element); Array<Real>::matrix_iterator node_coordinates_end = node_coordinates.end(dim, nb_nodes_per_element); for (; node_coordinates_it != node_coordinates_end; ++node_coordinates_it) { for (UInt i = 0; i < nb_quad_points; i++, ++directing_cosines_it) { Matrix<Real> & nodes = *node_coordinates_it; Matrix<Real> & cosines = *directing_cosines_it; computeDirectingCosinesOnQuad(nodes, cosines); } } // Mauro: the directing_cosines internal is defined on the quadrature points of each element AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialReinforcement<dim>::assembleStiffnessMatrix( const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh & mesh = model->getMesh(); Mesh::type_iterator type_it = mesh.firstType(dim, ghost_type); Mesh::type_iterator type_end = mesh.lastType(dim, ghost_type); for (; type_it != type_end; ++type_it) { assembleStiffnessMatrixInterface(type, *type_it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Computes the reinforcement stiffness matrix (Gomes & Awruch, 2001) * \f[ * \mathbf{K}_e = \sum_{i=1}^R{A_i\int_{S_i}{\mathbf{B}^T * \mathbf{C}_i^T \mathbf{D}_{s, i} \mathbf{C}_i \mathbf{B}\,\mathrm{d}s}} * \f] */ template <UInt dim> void MaterialReinforcement<dim>::assembleStiffnessMatrixInterface( const ElementType & interface_type, const ElementType & background_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt voigt_size = getTangentStiffnessVoigtSize(dim); SparseMatrix & K = const_cast<SparseMatrix &>(model->getStiffnessMatrix()); FEEngine & background_engine = model->getFEEngine(); FEEngine & interface_engine = model->getFEEngine("EmbeddedInterfaceFEEngine"); Array<UInt> & elem_filter = element_filter(interface_type, ghost_type); Array<Real> & grad_u = gradu_embedded(interface_type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nodes_per_background_e = Mesh::getNbNodesPerElement(background_type); UInt nb_quadrature_points = interface_engine.getNbIntegrationPoints(interface_type, ghost_type); UInt back_dof = dim * nodes_per_background_e; UInt integrant_size = back_dof; grad_u.resize(nb_quadrature_points * nb_element); Array<Real> * tangent_moduli = new Array<Real>( nb_element * nb_quadrature_points, 1, "interface_tangent_moduli"); tangent_moduli->clear(); computeTangentModuli(interface_type, *tangent_moduli, ghost_type); Array<Real> & shapesd = shape_derivatives(interface_type, ghost_type) -> operator()(background_type, ghost_type); Array<Real> * integrant = new Array<Real>(nb_element * nb_quadrature_points, integrant_size * integrant_size, "B^t*C^t*D*C*B"); integrant->clear(); /// Temporary matrices for integrant product Matrix<Real> Bvoigt(voigt_size, back_dof); Matrix<Real> DC(voigt_size, voigt_size); Matrix<Real> DCB(voigt_size, back_dof); Matrix<Real> CtDCB(voigt_size, back_dof); Array<Real>::scalar_iterator D_it = tangent_moduli->begin(); Array<Real>::scalar_iterator D_end = tangent_moduli->end(); Array<Real>::matrix_iterator C_it = directing_cosines(interface_type, ghost_type) .begin(voigt_size, voigt_size); Array<Real>::matrix_iterator B_it = shapesd.begin(dim, nodes_per_background_e); Array<Real>::matrix_iterator integrant_it = integrant->begin(integrant_size, integrant_size); for (; D_it != D_end; ++D_it, ++C_it, ++B_it, ++integrant_it) { Real & D = *D_it; Matrix<Real> & C = *C_it; Matrix<Real> & B = *B_it; Matrix<Real> & BtCtDCB = *integrant_it; VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(B, Bvoigt, nodes_per_background_e); DC.clear(); DC(0, 0) = D * area; DC *= C; DCB.mul<false, false>(DC, Bvoigt); CtDCB.mul<true, false>(C, DCB); BtCtDCB.mul<true, false>(Bvoigt, CtDCB); } delete tangent_moduli; Array<Real> * K_interface = new Array<Real>( nb_element, integrant_size * integrant_size, "K_interface"); interface_engine.integrate(*integrant, *K_interface, integrant_size * integrant_size, interface_type, ghost_type, elem_filter); delete integrant; // Mauro: Here K_interface contains the local stiffness matrices, // directing_cosines contains the information about the orientation // of the reinforcements, any rotation of the local stiffness matrix // can be done here Array<UInt> * background_filter = new Array<UInt>(nb_element, 1, "background_filter"); filterInterfaceBackgroundElements(*background_filter, background_type, interface_type, ghost_type); background_engine.assembleMatrix(*K_interface, K, dim, background_type, ghost_type, *background_filter); delete K_interface; delete background_filter; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /// In this function, type and ghost_type refer to background elements template <UInt dim> void MaterialReinforcement<dim>::computeBackgroundShapeDerivatives( const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh & interface_mesh = model->getInterfaceMesh(); FEEngine & engine = model->getFEEngine(); FEEngine & interface_engine = model->getFEEngine("EmbeddedInterfaceFEEngine"); Mesh::type_iterator interface_type = interface_mesh.firstType(); Mesh::type_iterator interface_last = interface_mesh.lastType(); for (; interface_type != interface_last; ++interface_type) { Array<UInt> & filter = element_filter(*interface_type, ghost_type); const UInt nb_elements = filter.getSize(); const UInt nb_nodes = Mesh::getNbNodesPerElement(type); const UInt nb_quad_per_element = interface_engine.getNbIntegrationPoints(*interface_type); Array<Real> quad_pos(nb_quad_per_element * nb_elements, dim, "interface_quad_points"); quad_pos.resize(nb_quad_per_element * nb_elements); interface_engine.interpolateOnIntegrationPoints( interface_mesh.getNodes(), quad_pos, dim, *interface_type, ghost_type, filter); Array<Real> & background_shapesd = shape_derivatives(*interface_type, ghost_type) -> operator()(type, ghost_type); background_shapesd.clear(); Array<UInt> * background_elements = new Array<UInt>( nb_elements, 1, "computeBackgroundShapeDerivatives:background_filter"); filterInterfaceBackgroundElements(*background_elements, type, *interface_type, ghost_type); Array<UInt>::scalar_iterator back_it = background_elements->begin(), back_end = background_elements->end(); Array<Real>::matrix_iterator shapesd_it = background_shapesd.begin(dim, nb_nodes); Array<Real>::vector_iterator quad_pos_it = quad_pos.begin(dim); for (; back_it != back_end; ++back_it) { for (UInt i = 0; i < nb_quad_per_element; i++, ++shapesd_it, ++quad_pos_it) engine.computeShapeDerivatives(*quad_pos_it, *back_it, type, *shapesd_it, ghost_type); } delete background_elements; } AKANTU_DEBUG_OUT(); } template <UInt dim> Real MaterialReinforcement<dim>::getEnergy(std::string id) { AKANTU_DEBUG_IN(); if (id == "potential") { Real epot = 0.; computePotentialEnergyByElements(); Mesh::type_iterator it = element_filter.firstType(spatial_dimension), end = element_filter.lastType(spatial_dimension); for (; it != end; ++it) { FEEngine & interface_engine = model->getFEEngine("EmbeddedInterfaceFEEngine"); epot += interface_engine.integrate(potential_energy(*it, _not_ghost), *it, _not_ghost, element_filter(*it, _not_ghost)); epot *= area; } return epot; } AKANTU_DEBUG_OUT(); return 0; } // /* -------------------------------------------------------------------------- // */ // template<UInt dim> // ElementTypeMap<UInt> MaterialReinforcement<dim>::getInternalDataPerElem(const // ID & field_name, // const // ElementKind // & // kind, // const // ID & // fe_engine_id) // const // { // return Material::getInternalDataPerElem(field_name, kind, // "EmbeddedInterfaceFEEngine"); // } // /* -------------------------------------------------------------------------- // */ // // Author is Guillaume Anciaux, see material.cc // template<UInt dim> // void MaterialReinforcement<dim>::flattenInternal(const std::string & // field_id, // ElementTypeMapArray<Real> & // internal_flat, // const GhostType ghost_type, // ElementKind element_kind) // const { // AKANTU_DEBUG_IN(); // if (field_id == "stress_embedded" || field_id == "inelastic_strain") { // Material::flattenInternalIntern(field_id, // internal_flat, // 1, // ghost_type, // _ek_not_defined, // &(this->element_filter), // &(this->model->getInterfaceMesh())); // } // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialReinforcement); /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh index ef6a4c8b1..fd8c6b52e 100644 --- a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh +++ b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh @@ -1,200 +1,200 @@ /** * @file material_reinforcement.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Fri Mar 13 2015 * @date last modification: Tue Nov 24 2015 * * @brief Reinforcement material * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_REINFORCEMENT_HH__ #define __AKANTU_MATERIAL_REINFORCEMENT_HH__ #include "aka_common.hh" #include "material.hh" #include "embedded_interface_model.hh" #include "embedded_internal_field.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /** * @brief Material used to represent embedded reinforcements * * This class is used for computing the reinforcement stiffness matrix * along with the reinforcement residual. Room is made for constitutive law, * but actual use of contitutive laws is made in MaterialReinforcementTemplate. * * Be careful with the dimensions in this class : * - this->spatial_dimension is always 1 * - the template parameter dim is the dimension of the problem */ template <UInt dim> class MaterialReinforcement : virtual public Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: /// Constructor MaterialReinforcement(SolidMechanicsModel & model, UInt spatial_dimension, const Mesh & mesh, FEEngine & fe_engine, const ID & id = ""); /// Destructor virtual ~MaterialReinforcement(); protected: void initialize(SolidMechanicsModel & a_model); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// Init the material virtual void initMaterial(); /// Init the background shape derivatives void initBackgroundShapeDerivatives(); /// Init the cosine matrices void initDirectingCosines(); /// Assemble stiffness matrix virtual void assembleStiffnessMatrix(GhostType ghost_type); /// Update the residual virtual void updateResidual(GhostType ghost_type = _not_ghost); /// Assembled the residual virtual void assembleResidual(GhostType ghost_type); /// Compute all the stresses ! virtual void computeAllStresses(GhostType ghost_type); /// Compute the stiffness parameter for elements of a type virtual void computeTangentModuli(const ElementType & type, Array<Real> & tangent, GhostType ghost_type) = 0; /// Compute energy virtual Real getEnergy(std::string id); // virtual ElementTypeMap<UInt> getInternalDataPerElem(const ID & field_name, // const ElementKind & // kind, // const ID & // fe_engine_id) const; // /// Reimplementation of Material's function to accomodate for interface // mesh // virtual void flattenInternal(const std::string & field_id, // ElementTypeMapArray<Real> & internal_flat, // const GhostType ghost_type = _not_ghost, // ElementKind element_kind = _ek_not_defined) // const; /* ------------------------------------------------------------------------ */ /* Protected methods */ /* ------------------------------------------------------------------------ */ protected: /// Allocate the background shape derivatives void allocBackgroundShapeDerivatives(); /// Compute the directing cosines matrix for one element type void computeDirectingCosines(const ElementType & type, GhostType ghost_type); /// Compute the directing cosines matrix on quadrature points. inline void computeDirectingCosinesOnQuad(const Matrix<Real> & nodes, Matrix<Real> & cosines); /// Assemble the stiffness matrix for an element type (typically _segment_2) void assembleStiffnessMatrix(const ElementType & type, GhostType ghost_type); /// Assemble the stiffness matrix for background & interface types void assembleStiffnessMatrixInterface(const ElementType & interface_type, const ElementType & background_type, GhostType ghost_type); /// Compute the background shape derivatives for a type void computeBackgroundShapeDerivatives(const ElementType & type, GhostType ghost_type); /// Filter elements crossed by interface of a type void filterInterfaceBackgroundElements(Array<UInt> & filter, const ElementType & type, const ElementType & interface_type, GhostType ghost_type); /// Assemble the residual of one type of element (typically _segment_2) void assembleInternalForces(const ElementType & type, GhostType ghost_type); /// Assemble the residual for a pair of elements void assembleInternalForcesInterface(const ElementType & interface_type, const ElementType & background_type, GhostType ghost_type); // TODO figure out why voigt size is 4 in 2D inline void stressTensorToVoigtVector(const Matrix<Real> & tensor, Vector<Real> & vector); inline void strainTensorToVoigtVector(const Matrix<Real> & tensor, Vector<Real> & vector); /// Compute gradu on the interface quadrature points virtual void computeGradU(const ElementType & type, GhostType ghost_type); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Embedded model EmbeddedInterfaceModel * model; /// Stress in the reinforcement InternalField<Real> stress_embedded; /// Gradu of concrete on reinforcement InternalField<Real> gradu_embedded; /// C matrix on quad InternalField<Real> directing_cosines; /// Prestress on quad InternalField<Real> pre_stress; /// Cross-sectional area Real area; /// Background mesh shape derivatives ElementTypeMap<ElementTypeMapArray<Real> *> shape_derivatives; }; #include "material_reinforcement_inline_impl.cc" -__END_AKANTU__ +} // akantu #endif // __AKANTU_MATERIAL_REINFORCEMENT_HH__ diff --git a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template.hh b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template.hh index 2a6e23721..3c489e38a 100644 --- a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template.hh +++ b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template.hh @@ -1,109 +1,109 @@ /** * @file material_reinforcement_template.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Wed Mar 25 2015 * @date last modification: Mon Jun 01 2015 * * @brief Reinforcement material templated with constitutive law * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_REINFORCEMENT_TEMPLATE_HH__ #define __AKANTU_MATERIAL_REINFORCEMENT_TEMPLATE_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_reinforcement.hh" #include "material_elastic.hh" #include "material_linear_isotropic_hardening.hh" -__BEGIN_AKANTU__ +namespace akantu { /** * @brief Implementation of MaterialReinforcement with 1D constitutive law * @see MaterialReinforcement, MaterialElastic * * This class is a reinforcement featuring a constitutive law. * <strong>Be careful !</strong> Because of multiple inheritance, this class * forms a diamond. */ template<UInt dim, class ConstLaw = MaterialElastic<1> > class MaterialReinforcementTemplate : public MaterialReinforcement<dim>, public ConstLaw { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: /// Constructor MaterialReinforcementTemplate(SolidMechanicsModel & a_model, const ID & id = ""); /// Destructor virtual ~MaterialReinforcementTemplate(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// Initialises the material void initMaterial(); /// Compute the stiffness parameter for elements of a type virtual void computeTangentModuli(const ElementType & type, Array<Real> & tangent, GhostType ghost_type); /// Computes stress used by constitutive law virtual void computeStress(ElementType type, GhostType ghost_type); /// Computes gradu to be used by the constitutive law virtual void computeGradU(const ElementType & type, GhostType ghost_type); /// Compute the potential energy of the reinforcement virtual void computePotentialEnergy(ElementType type, GhostType ghost_type = _not_ghost); /// Get energy in reinforcement (currently limited to potential) virtual Real getEnergy(std::string id); protected: /** * @brief Compute interface gradu from bulk gradu * \f[ * \varepsilon_s = C \varepsilon_c * \f] */ inline void computeInterfaceGradUOnQuad(const Matrix<Real> & full_gradu, Real & gradu, const Matrix<Real> & C); }; #include "material_reinforcement_template_tmpl.hh" -__END_AKANTU__ +} // akantu #endif // __AKANTU_MATERIAL_REINFORCEMENT_TEMPLATE_HH__ diff --git a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc index a55a8e331..23bedea4a 100644 --- a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc +++ b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc @@ -1,292 +1,292 @@ /** * @file material_neohookean.cc * * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * * @date creation: Mon Apr 08 2013 * @date last modification: Tue Aug 04 2015 * * @brief Specialization of the material class for finite deformation * neo-hookean material * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_neohookean.hh" #include "solid_mechanics_model.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialNeohookean<spatial_dimension>::MaterialNeohookean( SolidMechanicsModel & model, const ID & id) : PlaneStressToolbox<spatial_dimension>(model, id) { AKANTU_DEBUG_IN(); this->registerParam("E", E, Real(0.), _pat_parsable | _pat_modifiable, "Young's modulus"); this->registerParam("nu", nu, Real(0.5), _pat_parsable | _pat_modifiable, "Poisson's ratio"); this->registerParam("lambda", lambda, _pat_readable, "First Lamé coefficient"); this->registerParam("mu", mu, _pat_readable, "Second Lamé coefficient"); this->registerParam("kapa", kpa, _pat_readable, "Bulk coefficient"); this->finite_deformation = true; this->initialize_third_axis_deformation = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialNeohookean<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); PlaneStressToolbox<spatial_dimension>::initMaterial(); if (spatial_dimension == 1) nu = 0.; this->updateInternalParameters(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> void MaterialNeohookean<2>::initMaterial() { AKANTU_DEBUG_IN(); PlaneStressToolbox<2>::initMaterial(); this->updateInternalParameters(); if (this->plane_stress) this->third_axis_deformation.setDefaultValue(1.); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialNeohookean<spatial_dimension>::updateInternalParameters() { lambda = nu * E / ((1 + nu) * (1 - 2 * nu)); mu = E / (2 * (1 + nu)); kpa = lambda + 2. / 3. * mu; } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialNeohookean<dim>::computeCauchyStressPlaneStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); PlaneStressToolbox<dim>::computeCauchyStressPlaneStress(el_type, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> void MaterialNeohookean<2>::computeCauchyStressPlaneStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real>::matrix_iterator gradu_it = this->gradu(el_type, ghost_type).begin(2, 2); Array<Real>::matrix_iterator gradu_end = this->gradu(el_type, ghost_type).end(2, 2); Array<Real>::matrix_iterator piola_it = this->piola_kirchhoff_2(el_type, ghost_type).begin(2, 2); Array<Real>::matrix_iterator stress_it = this->stress(el_type, ghost_type).begin(2, 2); Array<Real>::const_scalar_iterator c33_it = this->third_axis_deformation(el_type, ghost_type).begin(); Matrix<Real> F_tensor(2, 2); for (; gradu_it != gradu_end; ++gradu_it, ++piola_it, ++stress_it, ++c33_it) { Matrix<Real> & grad_u = *gradu_it; Matrix<Real> & piola = *piola_it; Matrix<Real> & sigma = *stress_it; gradUToF<2>(grad_u, F_tensor); computeCauchyStressOnQuad<2>(F_tensor, piola, sigma, *c33_it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialNeohookean<dim>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); computeStressOnQuad(grad_u, sigma); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> void MaterialNeohookean<2>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); if (this->plane_stress) { PlaneStressToolbox<2>::computeStress(el_type, ghost_type); Array<Real>::const_scalar_iterator c33_it = this->third_axis_deformation(el_type, ghost_type).begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); computeStressOnQuad(grad_u, sigma, *c33_it); ++c33_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } else { MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); computeStressOnQuad(grad_u, sigma); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialNeohookean<dim>::computeThirdAxisDeformation( __attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> void MaterialNeohookean<2>::computeThirdAxisDeformation(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(this->plane_stress, "The third component of the strain " "can only be computed for 2D " "problems in Plane Stress!!"); Array<Real>::scalar_iterator c33_it = this->third_axis_deformation(el_type, ghost_type).begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); computeThirdAxisDeformationOnQuad(grad_u, *c33_it); ++c33_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialNeohookean<spatial_dimension>::computePotentialEnergy( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Material::computePotentialEnergy(el_type, ghost_type); if (ghost_type != _not_ghost) return; Array<Real>::scalar_iterator epot = this->potential_energy(el_type, ghost_type).begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); computePotentialEnergyOnQuad(grad_u, *epot); ++epot; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialNeohookean<spatial_dimension>::computeTangentModuli( __attribute__((unused)) const ElementType & el_type, Array<Real> & tangent_matrix, __attribute__((unused)) GhostType ghost_type) { AKANTU_DEBUG_IN(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); computeTangentModuliOnQuad(tangent, grad_u); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> void MaterialNeohookean<2>::computeTangentModuli(__attribute__((unused)) const ElementType & el_type, Array<Real> & tangent_matrix, __attribute__((unused)) GhostType ghost_type) { AKANTU_DEBUG_IN(); if (this->plane_stress) { PlaneStressToolbox<2>::computeStress(el_type, ghost_type); Array<Real>::const_scalar_iterator c33_it = this->third_axis_deformation(el_type, ghost_type).begin(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); computeTangentModuliOnQuad(tangent, grad_u, *c33_it); ++c33_it; MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; } else { MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); computeTangentModuliOnQuad(tangent, grad_u); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> Real MaterialNeohookean<spatial_dimension>::getPushWaveSpeed( __attribute__((unused)) const Element & element) const { return sqrt((this->lambda + 2 * this->mu) / this->rho); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> Real MaterialNeohookean<spatial_dimension>::getShearWaveSpeed( __attribute__((unused)) const Element & element) const { return sqrt(this->mu / this->rho); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialNeohookean); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.hh b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.hh index a95a6998c..a0bcbd715 100644 --- a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.hh +++ b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.hh @@ -1,171 +1,171 @@ /** * @file material_neohookean.hh * * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 08 2015 * * @brief Material isotropic elastic * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" #include "plane_stress_toolbox.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_NEOHOOKEAN_HH__ #define __AKANTU_MATERIAL_NEOHOOKEAN_HH__ -__BEGIN_AKANTU__ +namespace 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) * - Plane_Stress : if 0: plane strain, else: plane stress (default: 0) */ template<UInt spatial_dimension> class MaterialNeohookean : public virtual PlaneStressToolbox<spatial_dimension> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialNeohookean(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialNeohookean() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the material computed parameter virtual void initMaterial(); /// constitutive law for all element of a type virtual void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// Computation of the cauchy stress for plane strain materials virtual void computeCauchyStressPlaneStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// Non linear computation of the third direction strain in 2D plane stress case virtual void computeThirdAxisDeformation(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the elastic potential energy virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the tangent stiffness matrix for an element type void computeTangentModuli(const ElementType & el_type, Array<Real> & tangent_matrix, GhostType ghost_type = _not_ghost); /// compute the p-wave speed in the material virtual Real getPushWaveSpeed(const Element & element) const; /// compute the s-wave speed in the material virtual Real getShearWaveSpeed(const Element & element) const; protected: /// constitutive law for a given quadrature point inline void computePiolaKirchhoffOnQuad(const Matrix<Real> &E, Matrix<Real> &S); /// constitutive law for a given quadrature point (first piola) inline void computeFirstPiolaKirchhoffOnQuad(const Matrix<Real> &grad_u, const Matrix<Real> &S, Matrix<Real> &P); /// constitutive law for a given quadrature point inline void computeDeltaStressOnQuad(const Matrix<Real> & grad_u, const Matrix<Real> & grad_delta_u, Matrix<Real> & delta_S); /// constitutive law for a given quadrature point inline void computeStressOnQuad(Matrix<Real> & grad_u, Matrix<Real> & S, const Real & C33 = 1.0 ); /// constitutive law for a given quadrature point inline void computeThirdAxisDeformationOnQuad(Matrix<Real> & grad_u, Real & c33_value); /// constitutive law for a given quadrature point //inline void updateStressOnQuad(const Matrix<Real> & sigma, // Matrix<Real> & cauchy_sigma); /// compute the potential energy for a quadrature point inline void computePotentialEnergyOnQuad(const Matrix<Real> & grad_u, Real & epot); /// compute the tangent stiffness matrix for an element void computeTangentModuliOnQuad(Matrix<Real> & tangent, Matrix<Real> & grad_u, const Real & C33 = 1.0 ); /// recompute the lame coefficient if E or nu changes virtual void updateInternalParameters(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ 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; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_neohookean_inline_impl.cc" -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_NEOHOOKEAN_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_non_local.cc b/src/model/solid_mechanics/materials/material_non_local.cc index 24d8d434d..2ef2aa5f6 100644 --- a/src/model/solid_mechanics/materials/material_non_local.cc +++ b/src/model/solid_mechanics/materials/material_non_local.cc @@ -1,168 +1,168 @@ /** * @file material_non_local.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sat Sep 26 2015 * @date last modification: Tue Dec 08 2015 * * @brief Implementation of material non-local * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_non_local.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt dim> MaterialNonLocal<dim>::MaterialNonLocal(SolidMechanicsModel & model, const ID & id) : Material(model, id) { AKANTU_DEBUG_IN(); NonLocalManager & manager = this->model->getNonLocalManager(); manager.registerNonLocalMaterial(*this); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> MaterialNonLocal<dim>::~MaterialNonLocal() {} /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialNonLocal<dim>::initMaterial() { this->registerNeighborhood(); this->insertQuadsInNeighborhoods(_not_ghost); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialNonLocal<dim>::insertQuadsInNeighborhoods( GhostType ghost_type) { NonLocalManager & manager = this->model->getNonLocalManager(); InternalField<Real> quadrature_points_coordinates( "quadrature_points_coordinates_tmp_nl", *this); quadrature_points_coordinates.initialize(dim); /// intialize quadrature point object IntegrationPoint q; q.ghost_type = ghost_type; q.kind = _ek_regular; Mesh::type_iterator it = this->element_filter.firstType( dim, ghost_type, _ek_regular); Mesh::type_iterator last_type = this->element_filter.lastType(dim, ghost_type, _ek_regular); for (; it != last_type; ++it) { q.type = *it; const Array<UInt> & elem_filter = this->element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element) { UInt nb_quad = this->fem->getNbIntegrationPoints(*it, ghost_type); UInt nb_tot_quad = nb_quad * nb_element; Array<Real> & quads = quadrature_points_coordinates(*it, ghost_type); quads.resize(nb_tot_quad); this->model->getFEEngine().computeIntegrationPointsCoordinates( quads, *it, ghost_type, elem_filter); Array<Real>::const_vector_iterator quad = quads.begin(dim); UInt * elem = elem_filter.storage(); for (UInt e = 0; e < nb_element; ++e) { q.element = *elem; for (UInt nq = 0; nq < nb_quad; ++nq) { q.num_point = nq; q.global_num = q.element * nb_quad + nq; manager.insertQuad(q, *quad, this->name); ++quad; } ++elem; } } } } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialNonLocal<dim>::updateNonLocalInternals( ElementTypeMapReal & non_local_flattened, const ID & field_id, const UInt nb_component) { for (ghost_type_t::iterator g = ghost_type_t::begin(); g != ghost_type_t::end(); ++g) { GhostType ghost_type = *g; /// loop over all types in the material typedef ElementTypeMapArray<UInt>::type_iterator iterator; iterator it = this->element_filter.firstType(dim, ghost_type, _ek_regular); iterator last_type = this->element_filter.lastType(dim, ghost_type, _ek_regular); for (; it != last_type; ++it) { ElementType el_type = *it; Array<Real> & internal = this->getInternal<Real>(field_id)(el_type, ghost_type); Array<Real>::vector_iterator internal_it = internal.begin(nb_component); Array<Real> & internal_flat = non_local_flattened(el_type, ghost_type); Array<Real>::const_vector_iterator internal_flat_it = internal_flat.begin(nb_component); /// loop all elements for the given type const Array<UInt> & filter = this->element_filter(el_type, ghost_type); UInt nb_elements = filter.getSize(); UInt nb_quads = this->getFEEngine().getNbIntegrationPoints(el_type, ghost_type); for (UInt e = 0; e < nb_elements; ++e) { UInt global_el = filter(e); for (UInt q = 0; q < nb_quads; ++q, ++internal_it) { UInt global_quad = global_el * nb_quads + q; *internal_it = internal_flat_it[global_quad]; } } } } } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialNonLocal<dim>::updateResidual(__attribute__((unused)) GhostType ghost_type) { AKANTU_EXCEPTION("this method has not been implemented"); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialNonLocal<dim>::registerNeighborhood() { this->model->getNonLocalManager().registerNeighborhood(this->name, this->name); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialNonLocal); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_non_local.hh b/src/model/solid_mechanics/materials/material_non_local.hh index bee5198f4..e5ce642f8 100644 --- a/src/model/solid_mechanics/materials/material_non_local.hh +++ b/src/model/solid_mechanics/materials/material_non_local.hh @@ -1,86 +1,86 @@ /** * @file material_non_local.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Dec 08 2015 * * @brief Material class that handle the non locality of a law for example * damage. * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" #include "fe_engine.hh" #include "non_local_manager.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_NON_LOCAL_HH__ #define __AKANTU_MATERIAL_NON_LOCAL_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt dim> class MaterialNonLocal : public virtual Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialNonLocal(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialNonLocal(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the material computed parameter virtual void initMaterial(); virtual void updateResidual(GhostType ghost_type); /// insert the quadrature points in the neighborhoods of the non-local manager virtual void insertQuadsInNeighborhoods(GhostType ghost_type = _not_ghost); /// update the values in the non-local internal fields void updateNonLocalInternals(ElementTypeMapReal & non_local_flattened, const ID & field_id, const UInt nb_component); /// constitutive law virtual void computeNonLocalStresses(GhostType ghost_type = _not_ghost) = 0; /// register the neighborhoods for the material virtual void registerNeighborhood(); protected: virtual inline void onElementsAdded(const Array<Element> &, const NewElementsEvent &) { } protected: }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_NON_LOCAL_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc b/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc index 893ff9745..de5e4a295 100644 --- a/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc +++ b/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc @@ -1,36 +1,36 @@ /** * @file material_non_local_inline_impl.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Aug 31 2011 * @date last modification: Thu Oct 08 2015 * * @brief Non-local inline implementation * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu -__BEGIN_AKANTU__ +namespace akantu { diff --git a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc index 6757554d1..9bae61a24 100644 --- a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc +++ b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc @@ -1,203 +1,203 @@ /** * @file material_linear_isotropic_hardening.cc * * @author Ramin Aghababaei <ramin.aghababaei@epfl.ch> * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Benjamin Paccaud <benjamin.paccaud@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Apr 07 2014 * @date last modification: Tue Aug 18 2015 * * @brief Specialization of the material class for isotropic finite deformation * linear hardening plasticity * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_linear_isotropic_hardening.hh" #include "solid_mechanics_model.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt dim> MaterialLinearIsotropicHardening<dim>::MaterialLinearIsotropicHardening( SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialPlastic<dim>(model, id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialLinearIsotropicHardening<spatial_dimension>:: MaterialLinearIsotropicHardening(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id) : Material(model, dim, mesh, fe_engine, id), MaterialPlastic<spatial_dimension>(model, dim, mesh, fe_engine, id) {} /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialLinearIsotropicHardening<spatial_dimension>::computeStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialThermal<spatial_dimension>::computeStress(el_type, ghost_type); // infinitesimal and finite deformation auto sigma_th_it = this->sigma_th(el_type, ghost_type).begin(); auto previous_sigma_th_it = this->sigma_th.previous(el_type, ghost_type).begin(); auto previous_gradu_it = this->gradu.previous(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); auto previous_stress_it = this->stress.previous(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); auto inelastic_strain_it = this->inelastic_strain(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); auto previous_inelastic_strain_it = this->inelastic_strain.previous(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); auto iso_hardening_it = this->iso_hardening(el_type, ghost_type).begin(); auto previous_iso_hardening_it = this->iso_hardening.previous(el_type, ghost_type).begin(); // // Finite Deformations // if (this->finite_deformation) { auto previous_piola_kirchhoff_2_it = this->piola_kirchhoff_2.previous(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); auto green_strain_it = this->green_strain(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); auto & inelastic_strain_tensor = *inelastic_strain_it; auto & previous_inelastic_strain_tensor = *previous_inelastic_strain_it; auto & previous_grad_u = *previous_gradu_it; auto & previous_sigma = *previous_piola_kirchhoff_2_it; auto & green_strain = *green_strain_it; this->template gradUToGreenStrain<spatial_dimension>(grad_u, green_strain); Matrix<Real> previous_green_strain(spatial_dimension, spatial_dimension); this->template gradUToGreenStrain<spatial_dimension>(previous_grad_u, previous_green_strain); Matrix<Real> F_tensor(spatial_dimension, spatial_dimension); this->template gradUToF<spatial_dimension>(grad_u, F_tensor); computeStressOnQuad(green_strain, previous_green_strain, sigma, previous_sigma, inelastic_strain_tensor, previous_inelastic_strain_tensor, *iso_hardening_it, *previous_iso_hardening_it, *sigma_th_it, *previous_sigma_th_it, F_tensor); ++sigma_th_it; ++inelastic_strain_it; ++iso_hardening_it; ++previous_sigma_th_it; //++previous_stress_it; ++previous_gradu_it; ++green_strain_it; ++previous_inelastic_strain_it; ++previous_iso_hardening_it; ++previous_piola_kirchhoff_2_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } // Infinitesimal deformations else { MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); auto & inelastic_strain_tensor = *inelastic_strain_it; auto & previous_inelastic_strain_tensor = *previous_inelastic_strain_it; auto & previous_grad_u = *previous_gradu_it; auto & previous_sigma = *previous_stress_it; computeStressOnQuad( grad_u, previous_grad_u, sigma, previous_sigma, inelastic_strain_tensor, previous_inelastic_strain_tensor, *iso_hardening_it, *previous_iso_hardening_it, *sigma_th_it, *previous_sigma_th_it); ++sigma_th_it; ++inelastic_strain_it; ++iso_hardening_it; ++previous_sigma_th_it; ++previous_stress_it; ++previous_gradu_it; ++previous_inelastic_strain_it; ++previous_iso_hardening_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialLinearIsotropicHardening<spatial_dimension>::computeTangentModuli( const ElementType & el_type, Array<Real> & tangent_matrix, GhostType ghost_type) { AKANTU_DEBUG_IN(); auto previous_gradu_it = this->gradu.previous(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); auto previous_stress_it = this->stress.previous(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); auto iso_hardening = this->iso_hardening(el_type, ghost_type).begin(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); computeTangentModuliOnQuad(tangent, grad_u, *previous_gradu_it, sigma_tensor, *previous_stress_it, *iso_hardening); ++previous_gradu_it; ++previous_stress_it; ++iso_hardening; MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; this->was_stiffness_assembled = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialLinearIsotropicHardening); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh index 06fe1da02..2ebbf5280 100644 --- a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh +++ b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh @@ -1,121 +1,121 @@ /** * @file material_linear_isotropic_hardening.hh * * @author Ramin Aghababaei <ramin.aghababaei@epfl.ch> * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Benjamin Paccaud <benjamin.paccaud@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Mon Jun 01 2015 * * @brief Specialization of the material class for isotropic finite deformation linear hardening plasticity * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_voigthelper.hh" #include "material_plastic.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_LINEAR_ISOTROPIC_HARDENING_HH__ #define __AKANTU_MATERIAL_LINEAR_ISOTROPIC_HARDENING_HH__ -__BEGIN_AKANTU__ +namespace akantu { /** * Material plastic with a linear evolution of the yielding stress */ template <UInt spatial_dimension> class MaterialLinearIsotropicHardening : public MaterialPlastic<spatial_dimension> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialLinearIsotropicHardening(SolidMechanicsModel & model, const ID & id = ""); MaterialLinearIsotropicHardening(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id = ""); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// 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 computeTangentModuli(const ElementType & el_type, Array<Real> & tangent_matrix, GhostType ghost_type = _not_ghost); protected: /// Infinitesimal deformations inline void computeStressOnQuad(const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u, Matrix<Real> & sigma, const Matrix<Real> & previous_sigma, Matrix<Real> & inelas_strain, const Matrix<Real> & previous_inelas_strain, Real & iso_hardening, const Real & previous_iso_hardening, const Real & sigma_th, const Real & previous_sigma_th); /// Finite deformations inline void computeStressOnQuad(const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u, Matrix<Real> & sigma, const Matrix<Real> & previous_sigma, Matrix<Real> & inelas_strain, const Matrix<Real> & previous_inelas_strain, Real & iso_hardening, const Real & previous_iso_hardening, const Real & sigma_th, const Real & previous_sigma_th, const Matrix<Real> & F_tensor); inline void computeTangentModuliOnQuad(Matrix<Real> & tangent, const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u, const Matrix<Real> & sigma_tensor, const Matrix<Real> & previous_sigma_tensor, const Real & iso_hardening) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_linear_isotropic_hardening_inline_impl.cc" -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_LINEAR_ISOTROPIC_HARDENING_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc b/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc index bdcb5c66d..06bf3b8e9 100644 --- a/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc +++ b/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc @@ -1,203 +1,203 @@ /** * @file material_plastic.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Apr 07 2014 * @date last modification: Tue Aug 18 2015 * * @brief Implemantation of the akantu::MaterialPlastic class * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_plastic.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialPlastic<spatial_dimension>::MaterialPlastic(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialElastic<spatial_dimension>(model, id), iso_hardening("iso_hardening", *this), inelastic_strain("inelastic_strain", *this), plastic_energy("plastic_energy", *this), d_plastic_energy("d_plastic_energy", *this) { AKANTU_DEBUG_IN(); this->initialize(); AKANTU_DEBUG_OUT(); } template<UInt spatial_dimension> MaterialPlastic<spatial_dimension>::MaterialPlastic(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id) : Material(model, dim, mesh, fe_engine, id), MaterialElastic<spatial_dimension>(model, dim, mesh, fe_engine, id), iso_hardening ("iso_hardening" , *this, dim, fe_engine, this->element_filter), inelastic_strain("inelastic_strain", *this, dim, fe_engine, this->element_filter), plastic_energy ("plastic_energy" , *this, dim, fe_engine, this->element_filter), d_plastic_energy("d_plastic_energy", *this, dim, fe_engine, this->element_filter) { AKANTU_DEBUG_IN(); this->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialPlastic<spatial_dimension>::initialize() { this->registerParam( "h", h, Real(0.), _pat_parsable | _pat_modifiable, "Hardening modulus"); this->registerParam("sigma_y", sigma_y, Real(0.), _pat_parsable | _pat_modifiable, "Yield stress"); this->iso_hardening.initialize(1); this->iso_hardening.initializeHistory(); this->plastic_energy.initialize(1); this->d_plastic_energy.initialize(1); this->use_previous_stress = true; this->use_previous_gradu = true; this->use_previous_stress_thermal = true; this->inelastic_strain.initialize(spatial_dimension * spatial_dimension); this->inelastic_strain.initializeHistory(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> Real MaterialPlastic<spatial_dimension>::getEnergy(std::string type) { if (type == "plastic") return getPlasticEnergy(); else return MaterialElastic<spatial_dimension>::getEnergy(type); return 0.; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> Real MaterialPlastic<spatial_dimension>::getPlasticEnergy() { AKANTU_DEBUG_IN(); Real penergy = 0.; const Mesh & mesh = this->model->getFEEngine().getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost); Mesh::type_iterator end = mesh.lastType(spatial_dimension, _not_ghost); for(; it != end; ++it) { penergy += this->model->getFEEngine().integrate(plastic_energy(*it, _not_ghost), *it, _not_ghost, this->element_filter(*it, _not_ghost)); } AKANTU_DEBUG_OUT(); return penergy; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialPlastic<spatial_dimension>::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); if(ghost_type != _not_ghost) return; Array<Real>::scalar_iterator epot = this->potential_energy(el_type, ghost_type).begin(); Array<Real>::const_iterator< Matrix<Real> > inelastic_strain_it = this->inelastic_strain(el_type, ghost_type).begin(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix<Real> elastic_strain(spatial_dimension, spatial_dimension); elastic_strain.copy(grad_u); elastic_strain -= *inelastic_strain_it; MaterialElastic<spatial_dimension>::computePotentialEnergyOnQuad(elastic_strain, sigma, *epot); ++epot; ++inelastic_strain_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialPlastic<spatial_dimension>::updateEnergies(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialElastic<spatial_dimension>::updateEnergies(el_type, ghost_type); Array<Real>::iterator<> pe_it = this->plastic_energy(el_type, ghost_type).begin(); Array<Real>::iterator<> wp_it = this->d_plastic_energy(el_type, ghost_type).begin(); Array<Real>::iterator< Matrix<Real> > inelastic_strain_it = this->inelastic_strain(el_type, ghost_type).begin(spatial_dimension, spatial_dimension); Array<Real>::iterator< Matrix<Real> > previous_inelastic_strain_it = this->inelastic_strain.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator previous_sigma = this->stress.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix<Real> delta_strain_it(*inelastic_strain_it); delta_strain_it -= *previous_inelastic_strain_it; Matrix<Real> sigma_h(sigma); sigma_h += *previous_sigma; *wp_it = .5 * sigma_h.doubleDot(delta_strain_it); *pe_it += *wp_it; ++pe_it; ++wp_it; ++inelastic_strain_it; ++previous_inelastic_strain_it; ++previous_sigma; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialPlastic); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh b/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh index 8ca083a3e..7830851f9 100644 --- a/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh +++ b/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh @@ -1,142 +1,142 @@ /** * @file material_plastic.hh * * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 08 2015 * * @brief Common interface for plastic materials * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_elastic.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_PLASTIC_HH__ #define __AKANTU_MATERIAL_PLASTIC_HH__ -__BEGIN_AKANTU__ +namespace akantu { /** * Parent class for the plastic constitutive laws * parameters in the material files : * - h : Hardening parameter (default: 0) * - sigmay : Yield stress */ template<UInt dim> class MaterialPlastic : public MaterialElastic<dim> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialPlastic(SolidMechanicsModel & model, const ID & id = ""); MaterialPlastic(SolidMechanicsModel & model, UInt a_dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id = ""); protected: void initialize(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// get the energy specifying the type for the time step Real getEnergy(std::string type) override; /// Compute the plastic energy virtual void updateEnergies(ElementType el_type, GhostType ghost_type = _not_ghost); /// Compute the true potential energy void computePotentialEnergy(ElementType el_type, GhostType ghost_type) override; protected: /// compute the stress and inelastic strain for the quadrature point inline void computeStressAndInelasticStrainOnQuad(const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u, Matrix<Real> & sigma, const Matrix<Real> & previous_sigma, Matrix<Real> & inelas_strain, const Matrix<Real> & previous_inelas_strain, const Matrix<Real> & delta_inelastic_strain) const; inline void computeStressAndInelasticStrainOnQuad(const Matrix<Real> & delta_grad_u, Matrix<Real> & sigma, const Matrix<Real> & previous_sigma, Matrix<Real> & inelas_strain, const Matrix<Real> & previous_inelas_strain, const Matrix<Real> & delta_inelastic_strain) const; /// get the plastic energy for the time step Real getPlasticEnergy(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Yield stresss Real sigma_y; /// hardening modulus Real h; /// isotropic hardening, r InternalField<Real> iso_hardening; /// inelastic strain arrays ordered by element types (inelastic deformation) InternalField<Real> inelastic_strain; /// Plastic energy InternalField<Real> plastic_energy; /// @todo : add a coefficient beta that will multiply the plastic energy increment /// to compute the energy converted to heat /// Plastic energy increment InternalField<Real> d_plastic_energy; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #include "material_plastic_inline_impl.cc" #endif /* __AKANTU_MATERIAL_PLASTIC_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_python/material_python.cc b/src/model/solid_mechanics/materials/material_python/material_python.cc index 273890d16..4abed2e0e 100644 --- a/src/model/solid_mechanics/materials/material_python/material_python.cc +++ b/src/model/solid_mechanics/materials/material_python/material_python.cc @@ -1,212 +1,212 @@ /** * @file material_python.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * * @date creation: Fri Nov 13 2015 * @date last modification: Fri Nov 13 2015 * * @brief Material python implementation * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_python.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ MaterialPython::MaterialPython(SolidMechanicsModel & model, PyObject * obj, const ID & id) : Material(model, id), PythonFunctor(obj) { AKANTU_DEBUG_IN(); this->registerInternals(); std::vector<std::string> param_names = this->callFunctor<std::vector<std::string> >("registerParam"); for (UInt i = 0; i < param_names.size(); ++i) { std::stringstream sstr; sstr << "PythonParameter" << i; this->registerParam(param_names[i], local_params[param_names[i]], 0., _pat_parsable, sstr.str()); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialPython::registerInternals() { std::vector<std::string> internal_names = this->callFunctor<std::vector<std::string> >("registerInternals"); std::vector<UInt> internal_sizes; try { internal_sizes = this->callFunctor<std::vector<UInt> >("registerInternalSizes"); } catch (...) { internal_sizes.assign(internal_names.size(), 1); } for (UInt i = 0; i < internal_names.size(); ++i) { std::stringstream sstr; sstr << "PythonInternal" << i; this->internals[internal_names[i]] = new InternalField<Real>(internal_names[i], *this); AKANTU_DEBUG_INFO("alloc internal " << internal_names[i] << " " << this->internals[internal_names[i]]); this->internals[internal_names[i]]->initialize(internal_sizes[i]); } // making an internal with the quadrature points coordinates this->internals["quad_coordinates"] = new InternalField<Real>("quad_coordinates", *this); auto && coords = *this->internals["quad_coordinates"]; coords.initialize(this->getSpatialDimension()); } /* -------------------------------------------------------------------------- */ void MaterialPython::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); auto && coords = *this->internals["quad_coordinates"]; this->model->getFEEngine().computeIntegrationPointsCoordinates(coords, &this->element_filter); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialPython::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); std::map<std::string, Array<Real> *> internal_arrays; for (auto & i : this->internals) { auto & array = (*i.second)(el_type, ghost_type); auto & name = i.first; internal_arrays[name] = &array; } auto params = local_params; params["rho"] = this->rho; this->callFunctor<void>("computeStress", this->gradu(el_type, ghost_type), this->stress(el_type, ghost_type), internal_arrays, params); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <typename it_type> void MaterialPython::computeStress(Matrix<Real> & grad_u, Matrix<Real> & sigma, std::vector<it_type> & internal_iterators) { std::vector<Real> inputs; for (auto & i : internal_iterators) { inputs.push_back(*i); } for (UInt i = 0; i < inputs.size(); ++i) { *internal_iterators[i] = inputs[i]; } } /* -------------------------------------------------------------------------- */ // void MaterialPython::computeStress(ElementType el_type, GhostType ghost_type) // { // AKANTU_DEBUG_IN(); // typedef Array<Real>::iterator<Real> it_type; // std::vector<it_type> its; // for (auto & i : this->internals) { // its.push_back((*i)(el_type, ghost_type).begin()); // } // MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); // computeStress(grad_u, sigma, its); // for (auto & b : its) // ++b; // MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; // AKANTU_DEBUG_OUT(); // } // /* -------------------------------------------------------------------------- // */ // template <typename it_type> // void MaterialPython::computeStress(Matrix<Real> & grad_u, Matrix<Real> & // sigma, // std::vector<it_type> & internal_iterators) // { // std::vector<Real> inputs; // for (auto & i : internal_iterators) { // inputs.push_back(*i); // } // this->callFunctor<void>("computeStress", grad_u, sigma, inputs); // for (UInt i = 0; i < inputs.size(); ++i) { // *internal_iterators[i] = inputs[i]; // } // } /* -------------------------------------------------------------------------- */ void MaterialPython::computeTangentModuli(const ElementType & el_type, Array<Real> & tangent_matrix, GhostType ghost_type) { std::map<std::string, Array<Real> *> internal_arrays; for (auto & i : this->internals) { auto & array = (*i.second)(el_type, ghost_type); auto & name = i.first; internal_arrays[name] = &array; } auto params = local_params; params["rho"] = this->rho; this->callFunctor<void>("computeTangentModuli", this->gradu(el_type, ghost_type), tangent_matrix, internal_arrays, params); } /* -------------------------------------------------------------------------- */ Real MaterialPython::getPushWaveSpeed(__attribute__((unused)) const Element & element) const { auto params = local_params; params["rho"] = this->rho; return this->callFunctor<Real>("getPushWaveSpeed", params); } -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_python/material_python.hh b/src/model/solid_mechanics/materials/material_python/material_python.hh index d8de6de6b..52f8d3ff8 100644 --- a/src/model/solid_mechanics/materials/material_python/material_python.hh +++ b/src/model/solid_mechanics/materials/material_python/material_python.hh @@ -1,123 +1,123 @@ /** * @file material_python.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * * @date creation: Fri Nov 13 2015 * @date last modification: Fri Nov 13 2015 * * @brief Python material * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /** * @file material_python.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_PYTHON_HH__ #define __AKANTU_MATERIAL_PYTHON_HH__ /* -------------------------------------------------------------------------- */ #include "python_functor.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class MaterialPython : public Material, PythonFunctor { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialPython(SolidMechanicsModel & model, PyObject * obj, const ID & id = ""); virtual ~MaterialPython() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void registerInternals(); virtual void initMaterial(); /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// constitutive law for a given quad point template <typename it_type> void computeStress(Matrix<Real> & grad_u, Matrix<Real> & sigma, std::vector<it_type> & internal_iterators); /// compute the tangent stiffness matrix for an element type virtual void computeTangentModuli(const ElementType & el_type, Array<Real> & tangent_matrix, GhostType ghost_type = _not_ghost); /// compute the push wave speed of the material Real getPushWaveSpeed(const Element & element) const; protected: /// update the dissipated energy, must be called after the stress have been computed //virtual void updateEnergies(ElementType el_type, GhostType ghost_type){}; /// compute the tangent stiffness matrix for a given quadrature point //inline void computeTangentModuliOnQuad(Matrix<Real> & tangent, Real & dam){}; /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: //virtual Real getEnergy(std::string type){}; //virtual Real getEnergy(std::string energy_id, ElementType type, UInt index){}; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: std::map<std::string, Real> local_params; std::map<std::string, InternalField<Real> *> internals; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_PYTHON_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_thermal.cc b/src/model/solid_mechanics/materials/material_thermal.cc index 6c54c86c7..f0491b3a0 100644 --- a/src/model/solid_mechanics/materials/material_thermal.cc +++ b/src/model/solid_mechanics/materials/material_thermal.cc @@ -1,123 +1,123 @@ /** * @file material_thermal.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Aug 04 2015 * * @brief Specialization of the material class for the thermal material * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_thermal.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialThermal<spatial_dimension>::MaterialThermal(SolidMechanicsModel & model, const ID & id) : Material(model, id), delta_T("delta_T", *this), sigma_th("sigma_th", *this), use_previous_stress_thermal(false) { AKANTU_DEBUG_IN(); this->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialThermal<spatial_dimension>::MaterialThermal(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id) : Material(model, dim, mesh, fe_engine, id), delta_T("delta_T", *this, dim, fe_engine, this->element_filter), sigma_th("sigma_th", *this, dim, fe_engine, this->element_filter), use_previous_stress_thermal(false) { AKANTU_DEBUG_IN(); this->initialize(); AKANTU_DEBUG_OUT(); } template<UInt spatial_dimension> void MaterialThermal<spatial_dimension>::initialize() { this->registerParam("E" , E , Real(0. ) , _pat_parsable | _pat_modifiable, "Young's modulus" ); this->registerParam("nu" , nu , Real(0.5) , _pat_parsable | _pat_modifiable, "Poisson's ratio" ); this->registerParam("alpha" , alpha , Real(0. ) , _pat_parsable | _pat_modifiable, "Thermal expansion coefficient"); this->registerParam("delta_T", delta_T, _pat_parsable | _pat_modifiable, "Uniform temperature field"); delta_T.initialize(1); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialThermal<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); sigma_th.initialize(1); if(use_previous_stress_thermal) { sigma_th.initializeHistory(); } Material::initMaterial(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialThermal<dim>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real>::iterator<> delta_t_it = this->delta_T(el_type, ghost_type).begin(); Array<Real>::iterator<> sigma_th_it = this->sigma_th(el_type, ghost_type).begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); /// TODO : implement with the matrix alpha if (dim == 1) { *sigma_th_it = - this->E * this->alpha * *delta_t_it; } else { *sigma_th_it = - this->E/(1.-2.*this->nu) * this->alpha * *delta_t_it; } ++delta_t_it; ++sigma_th_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialThermal); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_thermal.hh b/src/model/solid_mechanics/materials/material_thermal.hh index e4e3abd75..17c5a6e7e 100644 --- a/src/model/solid_mechanics/materials/material_thermal.hh +++ b/src/model/solid_mechanics/materials/material_thermal.hh @@ -1,106 +1,106 @@ /** * @file material_thermal.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Aug 18 2015 * * @brief Material isotropic thermo-elastic * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_THERMAL_HH__ #define __AKANTU_MATERIAL_THERMAL_HH__ -__BEGIN_AKANTU__ +namespace akantu { template<UInt spatial_dimension> class MaterialThermal : public virtual Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialThermal(SolidMechanicsModel & model, const ID & id = ""); MaterialThermal(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id = ""); virtual ~MaterialThermal() {}; protected: void initialize(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void initMaterial(); /// constitutive law for all element of a type virtual void computeStress(ElementType el_type, GhostType ghost_type); /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Young modulus Real E; /// Poisson ratio Real nu; /// Thermal expansion coefficient /// TODO : implement alpha as a matrix Real alpha; /// Temperature field InternalField<Real> delta_T; /// Current thermal stress InternalField<Real> sigma_th; /// Tell if we need to use the previous thermal stress bool use_previous_stress_thermal; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_THERMAL_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc b/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc index a36d25944..ed5461e1e 100644 --- a/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc +++ b/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc @@ -1,299 +1,299 @@ /** * @file material_standard_linear_solid_deviatoric.cc * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Vladislav Yastrebov <vladislav.yastrebov@epfl.ch> * * @date creation: Wed May 04 2011 * @date last modification: Thu Oct 15 2015 * * @brief Material Visco-elastic * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_standard_linear_solid_deviatoric.hh" #include "solid_mechanics_model.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialStandardLinearSolidDeviatoric<spatial_dimension>::MaterialStandardLinearSolidDeviatoric(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialElastic<spatial_dimension>(model, id), stress_dev("stress_dev", *this), history_integral("history_integral", *this), dissipated_energy("dissipated_energy", *this) { AKANTU_DEBUG_IN(); this->registerParam("Eta", eta, Real(1.), _pat_parsable | _pat_modifiable, "Viscosity"); this->registerParam("Ev", Ev, Real(1.), _pat_parsable | _pat_modifiable, "Stiffness of the viscous element"); this->registerParam("Einf", E_inf, Real(1.), _pat_readable, "Stiffness of the elastic element"); UInt stress_size = spatial_dimension * spatial_dimension; this->stress_dev .initialize(stress_size); this->history_integral .initialize(stress_size); this->dissipated_energy.initialize(1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialStandardLinearSolidDeviatoric<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); updateInternalParameters(); MaterialElastic<spatial_dimension>::initMaterial(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialStandardLinearSolidDeviatoric<spatial_dimension>::updateInternalParameters() { MaterialElastic<spatial_dimension>::updateInternalParameters(); E_inf = this->E - this->Ev; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialStandardLinearSolidDeviatoric<spatial_dimension>::setToSteadyState(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real> & stress_dev_vect = stress_dev(el_type, ghost_type); Array<Real> & history_int_vect = history_integral(el_type, ghost_type); Array<Real>::matrix_iterator stress_d = stress_dev_vect.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator history_int = history_int_vect.begin(spatial_dimension, spatial_dimension); /// Loop on all quadrature points MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix<Real> & dev_s = *stress_d; Matrix<Real> & h = *history_int; /// Compute the first invariant of strain Real Theta = grad_u.trace(); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) { dev_s(i, j) = 2 * this->mu * (.5 * (grad_u(i,j) + grad_u(j,i)) - 1./3. * Theta *(i == j)); h(i, j) = 0.; } /// Save the deviator of stress ++stress_d; ++history_int; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialStandardLinearSolidDeviatoric<spatial_dimension>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real tau = 0.; // if(std::abs(Ev) > std::numeric_limits<Real>::epsilon()) tau = eta / Ev; Array<Real> & stress_dev_vect = stress_dev(el_type, ghost_type); Array<Real> & history_int_vect = history_integral(el_type, ghost_type); Array<Real>::matrix_iterator stress_d = stress_dev_vect.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator history_int = history_int_vect.begin(spatial_dimension, spatial_dimension); Matrix<Real> s(spatial_dimension, spatial_dimension); Real dt = this->model->getTimeStep(); Real exp_dt_tau = exp( -dt/tau ); Real exp_dt_tau_2 = exp( -.5*dt/tau ); Matrix<Real> epsilon_d(spatial_dimension, spatial_dimension); Matrix<Real> epsilon_v(spatial_dimension, spatial_dimension); /// Loop on all quadrature points MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix<Real> & dev_s = *stress_d; Matrix<Real> & h = *history_int; s.clear(); sigma.clear(); /// Compute the first invariant of strain Real gamma_inf = E_inf / this->E; Real gamma_v = Ev / this->E; this->template gradUToEpsilon<spatial_dimension>(grad_u, epsilon_d); Real Theta = epsilon_d.trace(); epsilon_v.eye(Theta / Real(3.)); epsilon_d -= epsilon_v; Matrix<Real> U_rond_prim(spatial_dimension, spatial_dimension); U_rond_prim.eye(gamma_inf * this->kpa * Theta); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) { s(i, j) = 2 * this->mu * epsilon_d(i, j); h(i, j) = exp_dt_tau * h(i, j) + exp_dt_tau_2 * (s(i, j) - dev_s(i, j)); dev_s(i, j) = s(i, j); sigma(i, j) = U_rond_prim(i,j) + gamma_inf * s(i, j) + gamma_v * h(i, j); } /// Save the deviator of stress ++stress_d; ++history_int; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; this->updateDissipatedEnergy(el_type, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialStandardLinearSolidDeviatoric<spatial_dimension>::updateDissipatedEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); // if(ghost_type == _ghost) return 0.; Real tau = 0.; tau = eta / Ev; Real * dis_energy = dissipated_energy(el_type, ghost_type).storage(); Array<Real> & stress_dev_vect = stress_dev(el_type, ghost_type); Array<Real> & history_int_vect = history_integral(el_type, ghost_type); Array<Real>::matrix_iterator stress_d = stress_dev_vect.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator history_int = history_int_vect.begin(spatial_dimension, spatial_dimension); Matrix<Real> q(spatial_dimension, spatial_dimension); Matrix<Real> q_rate(spatial_dimension, spatial_dimension); Matrix<Real> epsilon_d(spatial_dimension, spatial_dimension); Matrix<Real> epsilon_v(spatial_dimension, spatial_dimension); Real dt = this->model->getTimeStep(); Real gamma_v = Ev / this->E; Real alpha = 1. / (2. * this->mu * gamma_v); /// Loop on all quadrature points MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix<Real> & dev_s = *stress_d; Matrix<Real> & h = *history_int; /// Compute the first invariant of strain this->template gradUToEpsilon<spatial_dimension>(grad_u, epsilon_d); Real Theta = epsilon_d.trace(); epsilon_v.eye(Theta / Real(3.)); epsilon_d -= epsilon_v; q.copy(dev_s); q -= h; q *= gamma_v; q_rate.copy(dev_s); q_rate *= gamma_v; q_rate -= q; q_rate /= tau; for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) *dis_energy += (epsilon_d(i, j) - alpha * q(i, j)) * q_rate(i, j) * dt; /// Save the deviator of stress ++stress_d; ++history_int; ++dis_energy; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> Real MaterialStandardLinearSolidDeviatoric<spatial_dimension>::getDissipatedEnergy() const { AKANTU_DEBUG_IN(); Real de = 0.; const Mesh & mesh = this->model->getFEEngine().getMesh(); /// integrate the dissipated energy for each type of elements Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost); Mesh::type_iterator end = mesh.lastType(spatial_dimension, _not_ghost); for(; it != end; ++it) { de += this->model->getFEEngine().integrate(dissipated_energy(*it, _not_ghost), *it, _not_ghost, this->element_filter(*it, _not_ghost)); } AKANTU_DEBUG_OUT(); return de; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> Real MaterialStandardLinearSolidDeviatoric<spatial_dimension>::getDissipatedEnergy(ElementType type, UInt index) const { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = this->model->getFEEngine().getNbIntegrationPoints(type); Array<Real>::const_vector_iterator it = this->dissipated_energy(type, _not_ghost).begin(nb_quadrature_points); UInt gindex = (this->element_filter(type, _not_ghost))(index); AKANTU_DEBUG_OUT(); return this->model->getFEEngine().integrate(it[index], type, gindex); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> Real MaterialStandardLinearSolidDeviatoric<spatial_dimension>::getEnergy(std::string type) { if(type == "dissipated") return getDissipatedEnergy(); else if(type == "dissipated_sls_deviatoric") return getDissipatedEnergy(); else return MaterialElastic<spatial_dimension>::getEnergy(type); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> Real MaterialStandardLinearSolidDeviatoric<spatial_dimension>::getEnergy(std::string energy_id, ElementType type, UInt index) { if(energy_id == "dissipated") return getDissipatedEnergy(type, index); else if(energy_id == "dissipated_sls_deviatoric") return getDissipatedEnergy(type, index); else return MaterialElastic<spatial_dimension>::getEnergy(energy_id, type, index); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(MaterialStandardLinearSolidDeviatoric); -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.hh b/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.hh index 54eb0b7c1..9d4e4cc5d 100644 --- a/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.hh +++ b/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.hh @@ -1,137 +1,137 @@ /** * @file material_standard_linear_solid_deviatoric.hh * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Vladislav Yastrebov <vladislav.yastrebov@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 08 2015 * * @brief Material Visco-elastic, based on Standard Solid rheological model, see * [] J.C. Simo, T.J.R. Hughes, "Computational Inelasticity", Springer (1998), * see Sections 10.2 and 10.3 * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_elastic.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_STANDARD_LINEAR_SOLID_DEVIATORIC_HH__ #define __AKANTU_MATERIAL_STANDARD_LINEAR_SOLID_DEVIATORIC_HH__ -__BEGIN_AKANTU__ +namespace akantu { /** * Material standard linear solid deviatoric * * * @verbatim E_\inf ------|\/\/\|------ | | ---| |--- | | ----|\/\/\|--[|---- E_v \eta @endverbatim * * keyword : sls_deviatoric * * parameters in the material files : * - E : Initial Young's modulus @f$ E = E_i + E_v @f$ * - eta : viscosity * - Ev : stiffness of the viscous element */ template<UInt spatial_dimension> class MaterialStandardLinearSolidDeviatoric : public MaterialElastic<spatial_dimension> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialStandardLinearSolidDeviatoric(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialStandardLinearSolidDeviatoric() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the material computed parameter void initMaterial(); /// update the internal parameters (for modifiable parameters) virtual void updateInternalParameters(); /// set material to steady state void setToSteadyState(ElementType el_type, GhostType ghost_type = _not_ghost); /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); protected: /// update the dissipated energy, is called after the stress have been computed void updateDissipatedEnergy(ElementType el_type, GhostType ghost_type); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// give the dissipated energy for the time step Real getDissipatedEnergy() const; Real getDissipatedEnergy(ElementType type, UInt index) const; /// get the energy using an energy type string for the time step virtual Real getEnergy(std::string type); virtual Real getEnergy(std::string energy_id, ElementType type, UInt index); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// viscosity, viscous elastic modulus Real eta, Ev, E_inf; /// history of deviatoric stress InternalField<Real> stress_dev; /// Internal variable: history integral InternalField<Real> history_integral; /// Dissipated energy InternalField<Real> dissipated_energy; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MATERIAL_STANDARD_LINEAR_SOLID_DEVIATORIC_HH__ */ diff --git a/src/model/solid_mechanics/materials/plane_stress_toolbox.hh b/src/model/solid_mechanics/materials/plane_stress_toolbox.hh index 852158597..7f2b702e1 100644 --- a/src/model/solid_mechanics/materials/plane_stress_toolbox.hh +++ b/src/model/solid_mechanics/materials/plane_stress_toolbox.hh @@ -1,101 +1,101 @@ /** * @file plane_stress_toolbox.hh * * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Sep 16 2014 * @date last modification: Tue Aug 18 2015 * * @brief Tools to implement the plane stress behavior in a material * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_PLANE_STRESS_TOOLBOX_HH__ #define __AKANTU_PLANE_STRESS_TOOLBOX_HH__ -__BEGIN_AKANTU__ +namespace akantu { /** * Empty class in dimensions different from 2 * This class is only specialized for 2D in the tmpl file */ template <UInt dim, class ParentMaterial = Material> class PlaneStressToolbox : public ParentMaterial { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: PlaneStressToolbox(SolidMechanicsModel & model, const ID & id = "") : Material(model, id), ParentMaterial(model, id) {} PlaneStressToolbox(SolidMechanicsModel & model, UInt spatial_dimension, const Mesh & mesh, FEEngine & fe_engine, const ID & id = "") : Material(model, spatial_dimension, mesh, fe_engine, id), ParentMaterial(model, spatial_dimension, mesh, fe_engine, id) {} virtual ~PlaneStressToolbox() {} protected: void initialize(); public: virtual void computeAllCauchyStresses(GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_IN(); ParentMaterial::computeAllCauchyStresses(ghost_type); AKANTU_DEBUG_OUT(); } virtual void computeCauchyStressPlaneStress(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ERROR("The function \"computeCauchyStressPlaneStress\" can " "only be used in 2D Plane stress problems, which means " "that you made a mistake somewhere!! "); AKANTU_DEBUG_OUT(); } protected: bool initialize_third_axis_deformation; }; #define AKANTU_PLANE_STRESS_TOOL_SPEC(dim) \ template <> \ inline PlaneStressToolbox<dim, Material>::PlaneStressToolbox( \ SolidMechanicsModel & model, const ID & id) \ : Material(model, id) {} AKANTU_PLANE_STRESS_TOOL_SPEC(1) AKANTU_PLANE_STRESS_TOOL_SPEC(3) -__END_AKANTU__ +} // akantu #include "plane_stress_toolbox_tmpl.hh" #endif /* __AKANTU_PLANE_STRESS_TOOLBOX_HH__ */ diff --git a/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh b/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh index 6fc33053b..a16c33ffb 100644 --- a/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh +++ b/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh @@ -1,174 +1,174 @@ /** * @file plane_stress_toolbox_tmpl.hh * * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * * @date creation: Tue Sep 16 2014 * @date last modification: Tue Aug 18 2015 * * @brief 2D specialization of the akantu::PlaneStressToolbox class * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_PLANE_STRESS_TOOLBOX_TMPL_HH__ #define __AKANTU_PLANE_STRESS_TOOLBOX_TMPL_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <class ParentMaterial> class PlaneStressToolbox<2, ParentMaterial> : public ParentMaterial { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: PlaneStressToolbox(SolidMechanicsModel & model, const ID & id = ""); PlaneStressToolbox(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id = ""); virtual ~PlaneStressToolbox() {} AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ThirdAxisDeformation, third_axis_deformation, Real); protected: void initialize() { this->registerParam("Plane_Stress", plane_stress, false, _pat_parsmod, "Is plane stress"); } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ virtual void initMaterial() { ParentMaterial::initMaterial(); if (this->plane_stress && this->initialize_third_axis_deformation) { this->third_axis_deformation.initialize(1); this->third_axis_deformation.resize(); } } /* ------------------------------------------------------------------------ */ virtual void computeStress(ElementType el_type, GhostType ghost_type) { ParentMaterial::computeStress(el_type, ghost_type); if (this->plane_stress) computeThirdAxisDeformation(el_type, ghost_type); } /* ------------------------------------------------------------------------ */ virtual void computeThirdAxisDeformation(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type) {} /// Computation of Cauchy stress tensor in the case of finite deformation virtual void computeAllCauchyStresses(GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_IN(); if (this->plane_stress) { AKANTU_DEBUG_ASSERT(this->finite_deformation, "The Cauchy stress can only be computed if you are " "working in finite deformation."); // resizeInternalArray(stress); Mesh::type_iterator it = this->model->getFEEngine().getMesh().firstType(2, ghost_type); Mesh::type_iterator last_type = this->model->getFEEngine().getMesh().lastType(2, ghost_type); for (; it != last_type; ++it) this->computeCauchyStressPlaneStress(*it, ghost_type); } else ParentMaterial::computeAllCauchyStresses(ghost_type); AKANTU_DEBUG_OUT(); } virtual void computeCauchyStressPlaneStress(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost){}; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// third axis strain measure value InternalField<Real> third_axis_deformation; /// Plane stress or plane strain bool plane_stress; /// For non linear materials, the \epsilon_{zz} might be required bool initialize_third_axis_deformation; }; template <class ParentMaterial> inline PlaneStressToolbox<2, ParentMaterial>::PlaneStressToolbox( SolidMechanicsModel & model, const ID & id) : Material(model, id), ParentMaterial(model, id), third_axis_deformation("third_axis_deformation", *this), plane_stress(false), initialize_third_axis_deformation(false) { /// @todo Plane_Stress should not be possible to be modified after /// initMaterial (but before) this->initialize(); } template <class ParentMaterial> inline PlaneStressToolbox<2, ParentMaterial>::PlaneStressToolbox( SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id) : Material(model, dim, mesh, fe_engine, id), ParentMaterial(model, dim, mesh, fe_engine, id), third_axis_deformation("third_axis_deformation", *this, dim, fe_engine, this->element_filter), plane_stress(false), initialize_third_axis_deformation(false) { this->initialize(); } template <> inline PlaneStressToolbox<2, Material>::PlaneStressToolbox( SolidMechanicsModel & model, const ID & id) : Material(model, id), third_axis_deformation("third_axis_deformation", *this), plane_stress(false), initialize_third_axis_deformation(false) { /// @todo Plane_Stress should not be possible to be modified after /// initMaterial (but before) this->registerParam("Plane_Stress", plane_stress, false, _pat_parsmod, "Is plane stress"); } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_PLANE_STRESS_TOOLBOX_TMPL_HH__ */ diff --git a/src/model/solid_mechanics/materials/random_internal_field.hh b/src/model/solid_mechanics/materials/random_internal_field.hh index 595725b9a..dcca9ecb8 100644 --- a/src/model/solid_mechanics/materials/random_internal_field.hh +++ b/src/model/solid_mechanics/materials/random_internal_field.hh @@ -1,109 +1,109 @@ /** * @file random_internal_field.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Dec 08 2015 * * @brief Random internal material parameter * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_random_generator.hh" #include "internal_field.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_RANDOM_INTERNAL_FIELD_HH__ #define __AKANTU_RANDOM_INTERNAL_FIELD_HH__ -__BEGIN_AKANTU__ +namespace akantu { /** * class for the internal fields of materials with a random * distribution */ template<typename T, template<typename> class BaseField = InternalField, template<typename> class Generator = RandGenerator> class RandomInternalField : public BaseField<T> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: RandomInternalField(const ID & id, Material & material); virtual ~RandomInternalField(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ private: RandomInternalField operator=(__attribute__((unused)) const RandomInternalField & other) {}; public: AKANTU_GET_MACRO(RandomParameter, random_parameter, const RandomParameter<T>); /// initialize the field to a given number of component virtual void initialize(UInt nb_component); /// set the field to a given value void setDefaultValue(const T & value); /// set the specified random distribution to a given parameter void setRandomDistribution(const RandomParameter<T> & param); /// print the content virtual void printself(std::ostream & stream, int indent = 0) const; protected: virtual void setArrayValues(T * begin, T * end); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: inline operator Real() const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// random parameter containing the distribution and base value RandomParameter<T> random_parameter; }; /// standard output stream operator template<typename T> inline std::ostream & operator <<(std::ostream & stream, const RandomInternalField<T> & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_RANDOM_INTERNAL_FIELD_HH__ */ diff --git a/src/model/solid_mechanics/materials/random_internal_field_tmpl.hh b/src/model/solid_mechanics/materials/random_internal_field_tmpl.hh index 9cc50c67d..19c15c18d 100644 --- a/src/model/solid_mechanics/materials/random_internal_field_tmpl.hh +++ b/src/model/solid_mechanics/materials/random_internal_field_tmpl.hh @@ -1,125 +1,125 @@ /** * @file random_internal_field_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Tue Dec 08 2015 * * @brief Random internal material parameter implementation * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_random_generator.hh" #include "internal_field_tmpl.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_RANDOM_INTERNAL_FIELD_TMPL_HH__ #define __AKANTU_RANDOM_INTERNAL_FIELD_TMPL_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <typename T, template <typename> class BaseField, template <typename> class Generator> RandomInternalField<T, BaseField, Generator>::RandomInternalField( const ID & id, Material & material) : BaseField<T>(id, material), random_parameter(T()) {} /* -------------------------------------------------------------------------- */ template <typename T, template <typename> class BaseField, template <typename> class Generator> RandomInternalField<T, BaseField, Generator>::~RandomInternalField() {} /* -------------------------------------------------------------------------- */ template <typename T, template <typename> class BaseField, template <typename> class Generator> void RandomInternalField<T, BaseField, Generator>::initialize( UInt nb_component) { this->internalInitialize(nb_component); } /* ------------------------------------------------------------------------ */ template <typename T, template <typename> class BaseField, template <typename> class Generator> void RandomInternalField<T, BaseField, Generator>::setDefaultValue( const T & value) { random_parameter.setBaseValue(value); this->reset(); } /* ------------------------------------------------------------------------ */ template <typename T, template <typename> class BaseField, template <typename> class Generator> void RandomInternalField<T, BaseField, Generator>::setRandomDistribution( const RandomParameter<T> & param) { random_parameter = param; this->reset(); } /* ------------------------------------------------------------------------ */ template <typename T, template <typename> class BaseField, template <typename> class Generator> void RandomInternalField<T, BaseField, Generator>::printself( std::ostream & stream, int indent) const { stream << "RandomInternalField [ "; random_parameter.printself(stream); stream << " ]"; #if !defined(AKANTU_NDEBUG) if (AKANTU_DEBUG_TEST(dblDump)) { stream << std::endl; InternalField<T>::printself(stream, indent); } #endif } /* -------------------------------------------------------------------------- */ template <typename T, template <typename> class BaseField, template <typename> class Generator> void RandomInternalField<T, BaseField, Generator>::setArrayValues(T * begin, T * end) { random_parameter.template setValues<Generator>(begin, end); } /* -------------------------------------------------------------------------- */ template <typename T, template <typename> class BaseField, template <typename> class Generator> inline RandomInternalField<T, BaseField, Generator>::operator Real() const { return random_parameter.getBaseValue(); } /* -------------------------------------------------------------------------- */ template <> inline void ParameterTyped<RandomInternalField<Real> >::setAuto( const ParserParameter & in_param) { Parameter::setAuto(in_param); RandomParameter<Real> r = in_param; param.setRandomDistribution(r); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_RANDOM_INTERNAL_FIELD_TMPL_HH__ */ diff --git a/src/model/solid_mechanics/materials/weight_functions/base_weight_function.hh b/src/model/solid_mechanics/materials/weight_functions/base_weight_function.hh index a47b5c7d2..26cfe18a2 100644 --- a/src/model/solid_mechanics/materials/weight_functions/base_weight_function.hh +++ b/src/model/solid_mechanics/materials/weight_functions/base_weight_function.hh @@ -1,183 +1,183 @@ /** * @file base_weight_function.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Cyprien Wolff <cyprien.wolff@epfl.ch> * * @date creation: Mon Aug 24 2015 * @date last modification: Thu Oct 15 2015 * * @brief Base weight function for non local materials * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_types.hh" #include "parsable.hh" #include <cmath> #if defined(AKANTU_DEBUG_TOOLS) #include "aka_debug_tools.hh" #include <string> #endif #include "non_local_manager.hh" /* -------------------------------------------------------------------------- */ #include <vector> #include "material_damage.hh" #ifndef __AKANTU_BASE_WEIGHT_FUNCTION_HH__ #define __AKANTU_BASE_WEIGHT_FUNCTION_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* Normal weight function */ /* -------------------------------------------------------------------------- */ class BaseWeightFunction : public Parsable { public: /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ BaseWeightFunction(NonLocalManager & manager, const std::string & type = "base") : Parsable(_st_weight_function, "weight_function:" + type), manager(manager), type(type), spatial_dimension(manager.getModel().getSpatialDimension()) { this->registerParam("update_rate" , update_rate, 1U , _pat_parsmod, "Update frequency"); } virtual ~BaseWeightFunction() {} /* -------------------------------------------------------------------------- */ /* Methods */ /* -------------------------------------------------------------------------- */ /// initialize the weight function virtual inline void init(); /// update the internal parameters virtual void updateInternals() {}; /* ------------------------------------------------------------------------ */ /// set the non-local radius inline void setRadius(Real radius); /* ------------------------------------------------------------------------ */ /// compute the weight for a given distance between two quadrature points inline Real operator()(Real r, const __attribute__((unused)) IntegrationPoint & q1, const __attribute__((unused)) IntegrationPoint & q2); /// print function void printself(std::ostream & stream, int indent = 0) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "WeightFunction " << type << " [" << std::endl; Parsable::printself(stream, indent); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ /* Accessors */ /* -------------------------------------------------------------------------- */ public: /// get the radius Real getRadius() { return R; } /// get the update rate UInt getUpdateRate() { return update_rate; } public: /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ virtual UInt getNbDataForElements(__attribute__((unused)) const Array<Element> & elements, __attribute__((unused)) SynchronizationTag tag) const { return 0; } virtual inline void packElementData(__attribute__((unused)) CommunicationBuffer & buffer, __attribute__((unused)) const Array<Element> & elements, __attribute__((unused)) SynchronizationTag tag) const {} virtual inline void unpackElementData(__attribute__((unused)) CommunicationBuffer & buffer, __attribute__((unused)) const Array<Element> & elements, __attribute__((unused)) SynchronizationTag tag) {} /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(Type, type, const ID &); protected: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ /// reference to the non-local manager NonLocalManager & manager; /// the non-local radius Real R; /// the non-local radius squared Real R2; /// the update rate UInt update_rate; /// name of the type of weight function const std::string type; /// the spatial dimension UInt spatial_dimension; }; inline std::ostream & operator <<(std::ostream & stream, const BaseWeightFunction & _this) { _this.printself(stream); return stream; } #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "base_weight_function_inline_impl.cc" #endif -__END_AKANTU__ +} // akantu /* -------------------------------------------------------------------------- */ /* Include all other weight function types */ /* -------------------------------------------------------------------------- */ # include "damaged_weight_function.hh" # include "remove_damaged_weight_function.hh" # include "remove_damaged_with_damage_rate_weight_function.hh" # include "stress_based_weight_function.hh" /* -------------------------------------------------------------------------- */ #endif /* __AKANTU_BASE_WEIGHT_FUNCTION_HH__ */ diff --git a/src/model/solid_mechanics/materials/weight_functions/damaged_weight_function.hh b/src/model/solid_mechanics/materials/weight_functions/damaged_weight_function.hh index d0e3473c2..ad13d065b 100644 --- a/src/model/solid_mechanics/materials/weight_functions/damaged_weight_function.hh +++ b/src/model/solid_mechanics/materials/weight_functions/damaged_weight_function.hh @@ -1,83 +1,83 @@ /** * @file damaged_weight_function.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Cyprien Wolff <cyprien.wolff@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 15 2015 * * @brief Damaged weight function for non local materials * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "base_weight_function.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_DAMAGED_WEIGHT_FUNCTION_HH__ #define __AKANTU_DAMAGED_WEIGHT_FUNCTION_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* Damage weight function */ /* -------------------------------------------------------------------------- */ class DamagedWeightFunction : public BaseWeightFunction { public: /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ DamagedWeightFunction(NonLocalManager & manager) : BaseWeightFunction(manager, "damaged"), damage(NULL) { this->init(); } /* -------------------------------------------------------------------------- */ /* Base Weight Function inherited methods */ /* -------------------------------------------------------------------------- */ /// set the pointers of internals to the right flattend version virtual void init(); inline Real operator()(Real r, const __attribute__((unused)) IntegrationPoint & q1, const IntegrationPoint & q2); private: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ /// internal pointer to the current damage vector ElementTypeMapReal * damage; }; #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "damaged_weight_function_inline_impl.cc" #endif -__END_AKANTU__ +} // akantu #endif /* __AKANTU_DAMAGED_WEIGHT_FUNCTION_HH__ */ diff --git a/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function.hh b/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function.hh index f969ba02c..a42c54d75 100644 --- a/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function.hh +++ b/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function.hh @@ -1,99 +1,99 @@ /** * @file remove_damaged_weight_function.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Cyprien Wolff <cyprien.wolff@epfl.ch> * * @date creation: Mon Aug 24 2015 * @date last modification: Thu Oct 15 2015 * * @brief Removed damaged weight function for non local materials * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "base_weight_function.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_REMOVE_DAMAGED_WEIGHT_FUNCTION_HH__ #define __AKANTU_REMOVE_DAMAGED_WEIGHT_FUNCTION_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* Remove damaged weight function */ /* -------------------------------------------------------------------------- */ class RemoveDamagedWeightFunction : public BaseWeightFunction { public: /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ RemoveDamagedWeightFunction(NonLocalManager & manager) : BaseWeightFunction(manager, "remove_damaged"), damage(NULL){ this->registerParam("damage_limit", this->damage_limit, 1., _pat_parsable, "Damage Threshold"); this->init(); } /* -------------------------------------------------------------------------- */ /* Base Weight Function inherited methods */ /* -------------------------------------------------------------------------- */ virtual inline void init(); inline Real operator()(Real r, const __attribute__((unused)) IntegrationPoint & q1, const IntegrationPoint & q2); /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ virtual inline UInt getNbDataForElements(const Array<Element> & elements, SynchronizationTag tag) const; virtual inline void packElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag) const; virtual inline void unpackElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag); private: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ /// limit at which a point is considered as complitely broken Real damage_limit; /// internal pointer to the current damage vector ElementTypeMapReal * damage; }; #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "remove_damaged_weight_function_inline_impl.cc" #endif -__END_AKANTU__ +} // akantu #endif /* __AKANTU_REMOVE_DAMAGED_WEIGHT_FUNCTION_HH__ */ diff --git a/src/model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function.hh b/src/model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function.hh index a959aa1ab..dca670cba 100644 --- a/src/model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function.hh +++ b/src/model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function.hh @@ -1,82 +1,82 @@ /** * @file remove_damaged_with_damage_rate_weight_function.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Cyprien Wolff <cyprien.wolff@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 15 2015 * * @brief Removed damaged weight function for non local materials * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "base_weight_function.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_REMOVE_DAMAGED_WITH_DAMAGE_RATE_WEIGHT_FUNCTION_HH__ #define __AKANTU_REMOVE_DAMAGED_WITH_DAMAGE_RATE_WEIGHT_FUNCTION_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* Remove damaged with damage rate weight function */ /* -------------------------------------------------------------------------- */ class RemoveDamagedWithDamageRateWeightFunction : public BaseWeightFunction { public: /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ RemoveDamagedWithDamageRateWeightFunction(NonLocalManager & manager) : BaseWeightFunction(manager, "remove_damage_with_damage_rate"), damage_with_damage_rate(NULL) { this->registerParam<Real>("damage_limit", this->damage_limit_with_damage_rate, 1, _pat_parsable, "Damage Threshold"); this->init(); } /* -------------------------------------------------------------------------- */ /* Base Weight Function inherited methods */ /* -------------------------------------------------------------------------- */ inline Real operator()(Real r, const __attribute__((unused)) IntegrationPoint & q1, const IntegrationPoint & q2); virtual inline void init(); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// limit at which a point is considered as complitely broken Real damage_limit_with_damage_rate; /// internal pointer to the current damage vector ElementTypeMapReal * damage_with_damage_rate; }; #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "remove_damaged_with_damage_rate_weight_function_inline_impl.cc" #endif -__END_AKANTU__ +} // akantu #endif /* __AKANTU_REMOVE_DAMAGED_WITH_DAMAGE_WEIGHT_FUNCTION_HH__ */ diff --git a/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function.cc b/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function.cc index d1fe4c526..c3e111249 100644 --- a/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function.cc +++ b/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function.cc @@ -1,117 +1,117 @@ /** * @file stress_based_weight_function.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Aug 24 2015 * @date last modification: Wed Oct 07 2015 * * @brief implementation of the stres based weight function classes * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "stress_based_weight_function.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ StressBasedWeightFunction::StressBasedWeightFunction(NonLocalManager & manager) : BaseWeightFunction(manager, "stress_based") // stress_diag("stress_diag", material), selected_stress_diag(NULL), // stress_base("stress_base", material), selected_stress_base(NULL), // characteristic_size("lc", material), selected_characteristic_size(NULL) { // this->registerParam("ft", this->ft, 0., _pat_parsable, "Tensile strength"); // stress_diag.initialize(spatial_dimension); // stress_base.initialize(spatial_dimension * spatial_dimension); // characteristic_size.initialize(1); } /* -------------------------------------------------------------------------- */ /// During intialization the characteristic sizes for all quadrature /// points are computed void StressBasedWeightFunction::init() { // const Mesh & mesh = this->material.getModel().getFEEngine().getMesh(); // for (UInt g = _not_ghost; g <= _ghost; ++g) { // GhostType gt = GhostType(g); // Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt); // Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, gt); // for(; it != last_type; ++it) { // UInt nb_quadrature_points = // this->material.getModel().getFEEngine().getNbQuadraturePoints(*it, gt); // const Array<UInt> & element_filter = this->material.getElementFilter(*it, gt); // UInt nb_element = element_filter.getSize(); // Array<Real> ones(nb_element*nb_quadrature_points, 1, 1.); // Array<Real> & lc = characteristic_size(*it, gt); // this->material.getModel().getFEEngine().integrateOnQuadraturePoints(ones, // lc, // 1, // *it, // gt, // element_filter); // for (UInt q = 0; q < nb_quadrature_points * nb_element; q++) { // lc(q) = pow(lc(q), 1./ Real(spatial_dimension)); // } // } // } } /* -------------------------------------------------------------------------- */ /// computation of principals stresses and principal directions void StressBasedWeightFunction::updatePrincipalStress(__attribute__((unused)) GhostType ghost_type) { // AKANTU_DEBUG_IN(); // const Mesh & mesh = this->material.getModel().getFEEngine().getMesh(); // Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); // Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type); // for(; it != last_type; ++it) { // Array<Real>::const_matrix_iterator sigma = // this->material.getStress(*it, ghost_type).begin(spatial_dimension, spatial_dimension); // Array<Real>::vector_iterator eigenvalues = // stress_diag(*it, ghost_type).begin(spatial_dimension); // Array<Real>::vector_iterator eigenvalues_end = // stress_diag(*it, ghost_type).end(spatial_dimension); // Array<Real>::matrix_iterator eigenvector = // stress_base(*it, ghost_type).begin(spatial_dimension, spatial_dimension); // #ifndef __trick__ // Array<Real>::iterator<Real> cl = characteristic_size(*it, ghost_type).begin(); // #endif // UInt q = 0; // for(;eigenvalues != eigenvalues_end; ++sigma, ++eigenvalues, ++eigenvector, ++cl, ++q) { // sigma->eig(*eigenvalues, *eigenvector); // *eigenvalues /= ft; // #ifndef __trick__ // // specify a lower bound for principal stress based on the size of the element // for (UInt i = 0; i < spatial_dimension; ++i) { // (*eigenvalues)(i) = std::max(*cl / this->R, (*eigenvalues)(i)); // } // #endif // } // } // AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function.hh b/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function.hh index 56593df10..fd3e0744e 100644 --- a/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function.hh +++ b/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function.hh @@ -1,104 +1,104 @@ /** * @file stress_based_weight_function.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Cyprien Wolff <cyprien.wolff@epfl.ch> * * @date creation: Mon Aug 24 2015 * @date last modification: Thu Oct 15 2015 * * @brief Removed damaged weight function for non local materials * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "base_weight_function.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_STRESS_BASED_WEIGHT_FUNCTION_HH__ #define __AKANTU_STRESS_BASED_WEIGHT_FUNCTION_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /* Stress Based Weight */ /* -------------------------------------------------------------------------- */ /// based on based on Giry et al.: Stress-based nonlocal damage model, /// IJSS, 48, 2011 class StressBasedWeightFunction : public BaseWeightFunction { public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ StressBasedWeightFunction(NonLocalManager & manager); /* -------------------------------------------------------------------------- */ /* Base Weight Function inherited methods */ /* -------------------------------------------------------------------------- */ void init(); virtual inline void updateInternals(); void updatePrincipalStress(GhostType ghost_type); inline void updateQuadraturePointsCoordinates(ElementTypeMapArray<Real> & quadrature_points_coordinates); inline Real operator()(Real r, const IntegrationPoint & q1, const IntegrationPoint & q2); /// computation of ellipsoid inline Real computeRhoSquare(Real r, Vector<Real> & eigs, Matrix<Real> & eigenvects, Vector<Real> & x_s); protected: inline void setInternal(); private: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ /// tensile strength Real ft; /// prinicipal stresses ElementTypeMapReal * stress_diag; /// for preselection of types (optimization) ElementTypeMapReal * selected_stress_diag; /// principal directions ElementTypeMapReal * stress_base; /// lenght intrinisic to the material ElementTypeMapReal * characteristic_size; }; #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "stress_based_weight_function_inline_impl.cc" #endif -__END_AKANTU__ +} // akantu #endif /* __AKANTU_STRESS_BASED_WEIGHT_FUNCTION_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model.cc b/src/model/solid_mechanics/solid_mechanics_model.cc index ef421541b..76bbbe5ff 100644 --- a/src/model/solid_mechanics/solid_mechanics_model.cc +++ b/src/model/solid_mechanics/solid_mechanics_model.cc @@ -1,1511 +1,1511 @@ /** * @file solid_mechanics_model.cc * * @author Ramin Aghababaei <ramin.aghababaei@epfl.ch> * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Clement Roux <clement.roux@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue Jul 27 2010 * @date last modification: Tue Jan 19 2016 * * @brief Implementation of the SolidMechanicsModel class * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" #include "aka_math.hh" #include "element_group.hh" #include "element_synchronizer.hh" #include "group_manager_inline_impl.cc" #include "static_communicator.hh" #include "synchronizer_registry.hh" #include "sparse_matrix.hh" #include "dumpable_inline_impl.hh" #ifdef AKANTU_USE_IOHELPER #include "dumper_element_partition.hh" #include "dumper_elemental_field.hh" #include "dumper_field.hh" #include "dumper_homogenizing_field.hh" #include "dumper_internal_material_field.hh" #include "dumper_iohelper.hh" #include "dumper_material_padders.hh" #include "dumper_paraview.hh" #endif #ifdef AKANTU_DAMAGE_NON_LOCAL #include "non_local_manager.hh" #endif /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /** * A solid mechanics model need a mesh and a dimension to be created. the model * by it self can not do a lot, the good init functions should be called in * order to configure the model depending on what we want to do. * * @param mesh mesh representing the model we want to simulate * @param dim spatial dimension of the problem, if dim = 0 (default value) the * dimension of the problem is assumed to be the on of the mesh * @param id an id to identify the model */ SolidMechanicsModel::SolidMechanicsModel(Mesh & mesh, UInt dim, const ID & id, const MemoryID & memory_id) : Model(mesh, dim, id, memory_id), BoundaryCondition<SolidMechanicsModel>(), f_m2a(1.0), displacement(NULL), previous_displacement(NULL), displacement_increment(NULL), mass(NULL), velocity(NULL), acceleration(NULL), external_force(NULL), internal_force(NULL), blocked_dofs(NULL), current_position(NULL), mass_matrix(NULL), velocity_damping_matrix(NULL), stiffness_matrix(NULL), jacobian_matrix(NULL), material_index("material index", id, memory_id), material_local_numbering("material local numbering", id, memory_id), material_selector(new DefaultMaterialSelector(material_index)), is_default_material_selector(true), increment_flag(false), are_materials_instantiated(false), non_local_manager(NULL) { //, pbc_synch(NULL) { AKANTU_DEBUG_IN(); this->registerFEEngineObject<MyFEEngineType>("SolidMechanicsFEEngine", mesh, spatial_dimension); this->mesh.registerEventHandler(*this); #if defined(AKANTU_USE_IOHELPER) this->mesh.registerDumper<DumperParaview>("paraview_all", id, true); this->mesh.addDumpMesh(mesh, spatial_dimension, _not_ghost, _ek_regular); #endif this->initDOFManager(); this->registerDataAccessor(*this); if (this->mesh.isDistributed()) { auto & synchronizer = this->mesh.getElementSynchronizer(); this->registerSynchronizer(synchronizer, _gst_material_id); this->registerSynchronizer(synchronizer, _gst_smm_mass); this->registerSynchronizer(synchronizer, _gst_smm_stress); this->registerSynchronizer(synchronizer, _gst_smm_boundary); this->registerSynchronizer(synchronizer, _gst_for_dump); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SolidMechanicsModel::~SolidMechanicsModel() { AKANTU_DEBUG_IN(); if (is_default_material_selector) { delete material_selector; material_selector = NULL; } for (auto & internal : this->registered_internals) { delete internal.second; } #ifdef AKANTU_DAMAGE_NON_LOCAL delete non_local_manager; non_local_manager = NULL; #endif // delete pbc_synch; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::setTimeStep(Real time_step, const ID & solver_id) { Model::setTimeStep(time_step, solver_id); #if defined(AKANTU_USE_IOHELPER) this->mesh.getDumper().setTimeStep(time_step); #endif } /* -------------------------------------------------------------------------- */ /* Initialization */ /* -------------------------------------------------------------------------- */ /** * This function groups many of the initialization in on function. For most of * basics case the function should be enough. The functions initialize the * model, the internal vectors, set them to 0, and depending on the parameters * it also initialize the explicit or implicit solver. * * @param material_file the file containing the materials to use * @param method the analysis method wanted. See the akantu::AnalysisMethod for * the different possibilities */ void SolidMechanicsModel::initFull(const ModelOptions & options) { Model::initFull(options); const SolidMechanicsModelOptions & smm_options = dynamic_cast<const SolidMechanicsModelOptions &>(options); this->method = smm_options.analysis_method; // initialize the vectors this->initArrays(); if (!this->hasDefaultSolver()) this->initNewSolver(this->method); // initialize pbc if (this->pbc_pair.size() != 0) this->initPBC(); #ifdef AKANTU_DAMAGE_NON_LOCAL /// create the non-local manager object for non-local damage computations std::stringstream nl_manager_name; nl_manager_name << "NLManager" << this->id; this->non_local_manager = new NonLocalManager(*this, nl_manager_name.str(), this->memory_id); #endif // initialize the materials if (this->parser->getLastParsedFile() != "") { this->instantiateMaterials(); } if (!smm_options.no_init_materials) { this->initMaterials(); } // if (increment_flag) this->initBC(*this, *displacement, *displacement_increment, *external_force); // else // this->initBC(*this, *displacement, *external_force); } /* -------------------------------------------------------------------------- */ TimeStepSolverType SolidMechanicsModel::getDefaultSolverType() const { return _tsst_dynamic_lumped; } /* -------------------------------------------------------------------------- */ ModelSolverOptions SolidMechanicsModel::getDefaultSolverOptions( const TimeStepSolverType & type) const { ModelSolverOptions options; switch (type) { case _tsst_dynamic_lumped: { options.non_linear_solver_type = _nls_lumped; options.integration_scheme_type["displacement"] = _ist_central_difference; options.solution_type["displacement"] = IntegrationScheme::_acceleration; break; } case _tsst_static: { options.non_linear_solver_type = _nls_newton_raphson; options.integration_scheme_type["displacement"] = _ist_pseudo_time; options.solution_type["displacement"] = IntegrationScheme::_not_defined; break; } case _tsst_dynamic: { if (this->method == _explicit_consistent_mass) { options.non_linear_solver_type = _nls_newton_raphson; options.integration_scheme_type["displacement"] = _ist_central_difference; options.solution_type["displacement"] = IntegrationScheme::_acceleration; } else { options.non_linear_solver_type = _nls_newton_raphson; options.integration_scheme_type["displacement"] = _ist_trapezoidal_rule_2; options.solution_type["displacement"] = IntegrationScheme::_displacement; } break; } } return options; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initNewSolver(const AnalysisMethod & method) { ID solver_name; TimeStepSolverType tss_type; this->method = method; switch (this->method) { case _explicit_lumped_mass: { solver_name = "explicit_lumped"; tss_type = _tsst_dynamic_lumped; break; } case _explicit_consistent_mass: { solver_name = "explicit"; tss_type = _tsst_dynamic; break; } case _static: { solver_name = "static"; tss_type = _tsst_static; break; } case _implicit_dynamic: { solver_name = "implicit"; tss_type = _tsst_dynamic; break; } } if (!this->hasSolver(solver_name)) { ModelSolverOptions options = this->getDefaultSolverOptions(tss_type); this->getNewSolver(solver_name, tss_type, options.non_linear_solver_type); this->setIntegrationScheme(solver_name, "displacement", options.integration_scheme_type["displacement"], options.solution_type["displacement"]); this->setDefaultSolver(solver_name); } } /* -------------------------------------------------------------------------- */ template <typename T> void SolidMechanicsModel::allocNodalField(Array<T> *& array, __attribute__((unused)) UInt nb_component, const ID & name) { if (array == NULL) { UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_disp; sstr_disp << id << ":" << name; array = &(alloc<T>(sstr_disp.str(), nb_nodes, spatial_dimension, T())); } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initSolver( TimeStepSolverType time_step_solver_type, __attribute__((unused)) NonLinearSolverType non_linear_solver_type) { DOFManager & dof_manager = this->getDOFManager(); /* ------------------------------------------------------------------------ */ // for alloc type of solvers this->allocNodalField(this->displacement, spatial_dimension, "displacement"); this->allocNodalField(this->previous_displacement, spatial_dimension, "previous_displacement"); this->allocNodalField(this->displacement_increment, spatial_dimension, "displacement_increment"); this->allocNodalField(this->internal_force, spatial_dimension, "internal_force"); this->allocNodalField(this->external_force, spatial_dimension, "external_force"); this->allocNodalField(this->blocked_dofs, spatial_dimension, "blocked_dofs"); this->allocNodalField(this->current_position, spatial_dimension, "current_position"); /* ------------------------------------------------------------------------ */ if (!dof_manager.hasDOFs("displacement")) { dof_manager.registerDOFs("displacement", *this->displacement, _dst_nodal); dof_manager.registerBlockedDOFs("displacement", *this->blocked_dofs); dof_manager.registerDOFsIncrement("displacement", *this->displacement_increment); dof_manager.registerDOFsPrevious("displacement", *this->previous_displacement); } /* ------------------------------------------------------------------------ */ // for dynamic if (time_step_solver_type == _tsst_dynamic || time_step_solver_type == _tsst_dynamic_lumped) { this->allocNodalField(this->velocity, spatial_dimension, "velocity"); this->allocNodalField(this->acceleration, spatial_dimension, "acceleration"); if (!dof_manager.hasDOFsDerivatives("displacement", 1)) { dof_manager.registerDOFsDerivative("displacement", 1, *this->velocity); dof_manager.registerDOFsDerivative("displacement", 2, *this->acceleration); } } if (time_step_solver_type == _tsst_dynamic || time_step_solver_type == _tsst_static) { if (!dof_manager.hasMatrix("K")) { dof_manager.getNewMatrix("K", _symmetric); } if (!dof_manager.hasMatrix("J")) { dof_manager.getNewMatrix("J", "K"); } } } /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::initParallel(MeshPartition & partition, // DataAccessor<Element> * data_accessor) // { // AKANTU_DEBUG_IN(); // if (data_accessor == NULL) // data_accessor = this; // synch_parallel = &createParallelSynch(partition, *data_accessor); // synch_registry->registerSynchronizer(*synch_parallel, _gst_material_id); // synch_registry->registerSynchronizer(*synch_parallel, _gst_smm_mass); // synch_registry->registerSynchronizer(*synch_parallel, _gst_smm_stress); // synch_registry->registerSynchronizer(*synch_parallel, _gst_smm_boundary); // synch_registry->registerSynchronizer(*synch_parallel, _gst_for_dump); // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initFEEngineBoundary() { FEEngine & fem_boundary = getFEEngineBoundary(); fem_boundary.initShapeFunctions(_not_ghost); fem_boundary.initShapeFunctions(_ghost); fem_boundary.computeNormalsOnIntegrationPoints(_not_ghost); fem_boundary.computeNormalsOnIntegrationPoints(_ghost); } /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::initArraysPreviousDisplacment() { // AKANTU_DEBUG_IN(); // this->setIncrementFlagOn(); // if (not this->previous_displacement) { // this->allocNodalField(this->previous_displacement, spatial_dimension, // "previous_displacement"); // this->getDOFManager().registerDOFsPrevious("displacement", // *this->previous_displacement); // } // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ /** * Allocate all the needed vectors. By default their are not necessarily set to * 0 */ void SolidMechanicsModel::initArrays() { AKANTU_DEBUG_IN(); for (auto ghost_type : ghost_types) { for (auto type : mesh.elementTypes(spatial_dimension, ghost_type, _ek_not_defined)) { UInt nb_element = mesh.getNbElement(type, ghost_type); this->material_index.alloc(nb_element, 1, type, ghost_type); this->material_local_numbering.alloc(nb_element, 1, type, ghost_type); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Initialize the model,basically it pre-compute the shapes, shapes derivatives * and jacobian * */ void SolidMechanicsModel::initModel() { /// \todo add the current position as a parameter to initShapeFunctions for /// large deformation getFEEngine().initShapeFunctions(_not_ghost); getFEEngine().initShapeFunctions(_ghost); } /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::initPBC() { // Model::initPBC(); // registerPBCSynchronizer(); // // as long as there are ones on the diagonal of the matrix, we can put // // boudandary true for slaves // std::map<UInt, UInt>::iterator it = pbc_pair.begin(); // std::map<UInt, UInt>::iterator end = pbc_pair.end(); // UInt dim = mesh.getSpatialDimension(); // while (it != end) { // for (UInt i = 0; i < dim; ++i) // (*blocked_dofs)((*it).first, i) = true; // ++it; // } // } // /* -------------------------------------------------------------------------- // */ // void SolidMechanicsModel::registerPBCSynchronizer() { // pbc_synch = new PBCSynchronizer(pbc_pair); // synch_registry->registerSynchronizer(*pbc_synch, _gst_smm_uv); // synch_registry->registerSynchronizer(*pbc_synch, _gst_smm_mass); // synch_registry->registerSynchronizer(*pbc_synch, _gst_smm_res); // synch_registry->registerSynchronizer(*pbc_synch, _gst_for_dump); // // changeLocalEquationNumberForPBC(pbc_pair, mesh.getSpatialDimension()); // } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleResidual() { AKANTU_DEBUG_IN(); /* ------------------------------------------------------------------------ */ // computes the internal forces this->assembleInternalForces(); /* ------------------------------------------------------------------------ */ this->getDOFManager().assembleToResidual("displacement", *this->external_force, 1); this->getDOFManager().assembleToResidual("displacement", *this->internal_force, -1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleJacobian() { this->assembleStiffnessMatrix(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::predictor() {} /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::corrector() {} /* -------------------------------------------------------------------------- */ /** * This function computes the internal forces as F_{int} = \int_{\Omega} N * \sigma d\Omega@f$ */ void SolidMechanicsModel::assembleInternalForces() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Assemble the internal forces"); this->internal_force->clear(); // compute the stresses of local elements AKANTU_DEBUG_INFO("Compute local stresses"); for (auto & material : materials) { material->computeAllStresses(_not_ghost); } #ifdef AKANTU_DAMAGE_NON_LOCAL /* ------------------------------------------------------------------------ */ /* Computation of the non local part */ this->non_local_manager->computeAllNonLocalStresses(); #endif // communicate the stresses AKANTU_DEBUG_INFO("Send data for residual assembly"); this->asynchronousSynchronize(_gst_smm_stress); // assemble the forces due to local stresses AKANTU_DEBUG_INFO("Assemble residual for local elements"); for (auto & material : materials) { material->assembleInternalForces(_not_ghost); } // finalize communications AKANTU_DEBUG_INFO("Wait distant stresses"); this->waitEndSynchronize(_gst_smm_stress); // assemble the stresses due to ghost elements AKANTU_DEBUG_INFO("Assemble residual for ghost elements"); for (auto & material : materials) { material->assembleInternalForces(_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleStiffnessMatrix() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Assemble the new stiffness matrix."); // Check if materials need to recompute the matrix bool need_to_reassemble = false; for (auto & material : materials) { need_to_reassemble |= material->hasStiffnessMatrixChanged(); } if (need_to_reassemble) { this->getDOFManager().getMatrix("K").clear(); // call compute stiffness matrix on each local elements for (auto & material : materials) { material->assembleStiffnessMatrix(_not_ghost); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateCurrentPosition() { AKANTU_DEBUG_IN(); this->current_position->copy(this->mesh.getNodes()); auto cpos_it = this->current_position->begin(spatial_dimension); auto cpos_end = this->current_position->end(spatial_dimension); auto disp_it = this->displacement->begin(spatial_dimension); for (; cpos_it != cpos_end; ++cpos_it, ++disp_it) { *cpos_it += *disp_it; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::initializeUpdateResidualData() { // AKANTU_DEBUG_IN(); // UInt nb_nodes = mesh.getNbNodes(); // internal_force->resize(nb_nodes); // /// copy the forces in residual for boundary conditions // this->getDOFManager().assembleToResidual("displacement", // *this->external_force); // // start synchronization // this->asynchronousSynchronize(_gst_smm_uv); // this->waitEndSynchronize(_gst_smm_uv); // this->updateCurrentPosition(); // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ /* Explicit scheme */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::computeStresses() { // if (isExplicit()) { // // start synchronization // this->asynchronousSynchronize(_gst_smm_uv); // this->waitEndSynchronize(_gst_smm_uv); // // compute stresses on all local elements for each materials // std::vector<Material *>::iterator mat_it; // for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { // Material & mat = **mat_it; // mat.computeAllStresses(_not_ghost); // } // #ifdef AKANTU_DAMAGE_NON_LOCAL // /* Computation of the non local part */ // this->non_local_manager->computeAllNonLocalStresses(); // #endif // } else { // std::vector<Material *>::iterator mat_it; // for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { // Material & mat = **mat_it; // mat.computeAllStressesFromTangentModuli(_not_ghost); // } // } // } /* -------------------------------------------------------------------------- */ /* Implicit scheme */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ // /** // * Initialize the solver and create the sparse matrices needed. // * // */ // void SolidMechanicsModel::initSolver(__attribute__((unused)) // SolverOptions & options) { // UInt nb_global_nodes = mesh.getNbGlobalNodes(); // jacobian_matrix = &(this->getDOFManager().getNewMatrix("jacobian", // _symmetric)); // // jacobian_matrix->buildProfile(mesh, *dof_synchronizer, // spatial_dimension); // if (!isExplicit()) { // delete stiffness_matrix; // std::stringstream sstr_sti; // sstr_sti << id << ":stiffness_matrix"; // stiffness_matrix = &(this->getDOFManager().getNewMatrix("stiffness", // _symmetric)); // } // if (solver) solver->initialize(options); // } // /* -------------------------------------------------------------------------- // */ // void SolidMechanicsModel::initJacobianMatrix() { // // @todo make it more flexible: this is an ugly patch to treat the case of // non // // fix profile of the K matrix // delete jacobian_matrix; // jacobian_matrix = &(this->getDOFManager().getNewMatrix("jacobian", // "stiffness")); // std::stringstream sstr_solv; sstr_solv << id << ":solver"; // delete solver; // solver = new SolverMumps(*jacobian_matrix, sstr_solv.str()); // if(solver) // solver->initialize(_solver_no_options); // } /* -------------------------------------------------------------------------- */ /** * Initialize the implicit solver, either for dynamic or static cases, * * @param dynamic */ // void SolidMechanicsModel::initImplicit(bool dynamic) { // AKANTU_DEBUG_IN(); // method = dynamic ? _implicit_dynamic : _static; // if (!increment) // setIncrementFlagOn(); // initSolver(); // // if(method == _implicit_dynamic) { // // if(integrator) delete integrator; // // integrator = new TrapezoidalRule2(); // // } // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ // SparseMatrix & SolidMechanicsModel::initVelocityDampingMatrix() { // return this->getDOFManager().getNewMatrix("velocity_damping", "jacobian"); // } // /* -------------------------------------------------------------------------- // */ // void SolidMechanicsModel::implicitPred() { // AKANTU_DEBUG_IN(); // if(previous_displacement) previous_displacement->copy(*displacement); // if(method == _implicit_dynamic) // integrator->integrationSchemePred(time_step, // *displacement, // *velocity, // *acceleration, // *blocked_dofs); // AKANTU_DEBUG_OUT(); // } // /* -------------------------------------------------------------------------- // */ // void SolidMechanicsModel::implicitCorr() { // AKANTU_DEBUG_IN(); // if(method == _implicit_dynamic) { // integrator->integrationSchemeCorrDispl(time_step, // *displacement, // *velocity, // *acceleration, // *blocked_dofs, // *increment); // } else { // UInt nb_nodes = displacement->getSize(); // UInt nb_degree_of_freedom = displacement->getNbComponent() * nb_nodes; // Real * incr_val = increment->storage(); // Real * disp_val = displacement->storage(); // bool * boun_val = blocked_dofs->storage(); // for (UInt j = 0; j < nb_degree_of_freedom; ++j, ++disp_val, ++incr_val, // ++boun_val){ // *incr_val *= (1. - *boun_val); // *disp_val += *incr_val; // } // } // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::updateIncrement() { // AKANTU_DEBUG_IN(); // auto incr_it = this->displacement_increment->begin(spatial_dimension); // auto incr_end = this->displacement_increment->end(spatial_dimension); // auto disp_it = this->displacement->begin(spatial_dimension); // auto prev_disp_it = this->previous_displacement->begin(spatial_dimension); // for (; incr_it != incr_end; ++incr_it) { // *incr_it = *disp_it; // *incr_it -= *prev_disp_it; // } // AKANTU_DEBUG_OUT(); // } // /* -------------------------------------------------------------------------- // */ void SolidMechanicsModel::updatePreviousDisplacement() { // AKANTU_DEBUG_IN(); // AKANTU_DEBUG_ASSERT( // previous_displacement, // "The previous displacement has to be initialized." // << " Are you working with Finite or Ineslactic deformations?"); // previous_displacement->copy(*displacement); // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateDataForNonLocalCriterion( ElementTypeMapReal & criterion) { const ID field_name = criterion.getName(); for (auto & material : materials) { if (!material->isInternal<Real>(field_name, _ek_regular)) continue; for (auto ghost_type : ghost_types) { material->flattenInternal(field_name, criterion, ghost_type, _ek_regular); } } } /* -------------------------------------------------------------------------- */ /* Information */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::synchronizeBoundaries() { // AKANTU_DEBUG_IN(); // this->synchronize(_gst_smm_boundary); // AKANTU_DEBUG_OUT(); // } // /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::synchronizeResidual() { // AKANTU_DEBUG_IN(); // this->synchronize(_gst_smm_res); // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::setIncrementFlagOn() { // AKANTU_DEBUG_IN(); // if (!displacement_increment) { // this->allocNodalField(displacement_increment, spatial_dimension, // "displacement_increment"); // this->getDOFManager().registerDOFsIncrement("displacement", // *this->displacement_increment); // } // 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, _so_min); AKANTU_DEBUG_OUT(); return min_dt; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getStableTimeStep(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); Real min_dt = std::numeric_limits<Real>::max(); this->updateCurrentPosition(); Element elem; elem.ghost_type = ghost_type; elem.kind = _ek_regular; for (auto type : mesh.elementTypes(spatial_dimension, ghost_type, _ek_regular)) { elem.type = type; UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); UInt nb_element = mesh.getNbElement(type); auto mat_indexes = material_index(type, ghost_type).begin(); auto mat_loc_num = material_local_numbering(type, ghost_type).begin(); Array<Real> X(0, nb_nodes_per_element * spatial_dimension); FEEngine::extractNodalToElementField(mesh, *current_position, X, type, _not_ghost); auto X_el = X.begin(spatial_dimension, nb_nodes_per_element); for (UInt el = 0; el < nb_element; ++el, ++X_el, ++mat_indexes, ++mat_loc_num) { elem.element = *mat_loc_num; Real el_h = getFEEngine().getElementInradius(*X_el, type); Real el_c = this->materials[*mat_indexes]->getCelerity(elem); Real el_dt = el_h / el_c; min_dt = std::min(min_dt, el_dt); } } AKANTU_DEBUG_OUT(); return min_dt; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getKineticEnergy() { AKANTU_DEBUG_IN(); Real ekin = 0.; UInt nb_nodes = mesh.getNbNodes(); if (this->getDOFManager().hasLumpedMatrix("M")) { auto m_it = this->mass->begin(spatial_dimension); auto m_end = this->mass->end(spatial_dimension); auto v_it = this->velocity->begin(spatial_dimension); for (UInt n = 0; m_it != m_end; ++n, ++m_it, ++v_it) { const Vector<Real> & v = *v_it; const Vector<Real> & m = *m_it; Real mv2 = 0; bool is_local_node = mesh.isLocalOrMasterNode(n); // bool is_not_pbc_slave_node = !isPBCSlaveNode(n); bool count_node = is_local_node; // && is_not_pbc_slave_node; if (count_node) { for (UInt i = 0; i < spatial_dimension; ++i) { if (m(i) > std::numeric_limits<Real>::epsilon()) mv2 += v(i) * v(i) * m(i); } } ekin += mv2; } } else if (this->getDOFManager().hasMatrix("M")) { Array<Real> Mv(nb_nodes, spatial_dimension); this->getDOFManager().getMatrix("M").matVecMul(*this->velocity, Mv); Array<Real>::const_vector_iterator mv_it = Mv.begin(spatial_dimension); Array<Real>::const_vector_iterator mv_end = Mv.end(spatial_dimension); Array<Real>::const_vector_iterator v_it = this->velocity->begin(spatial_dimension); for (; mv_it != mv_end; ++mv_it, ++v_it) { ekin += v_it->dot(*mv_it); } } else { AKANTU_DEBUG_ERROR("No function called to assemble the mass matrix."); } StaticCommunicator::getStaticCommunicator().allReduce(ekin, _so_sum); AKANTU_DEBUG_OUT(); return ekin * .5; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getKineticEnergy(const ElementType & type, UInt index) { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(type); Array<Real> vel_on_quad(nb_quadrature_points, spatial_dimension); Array<UInt> filter_element(1, 1, index); getFEEngine().interpolateOnIntegrationPoints(*velocity, vel_on_quad, spatial_dimension, type, _not_ghost, filter_element); Array<Real>::vector_iterator vit = vel_on_quad.begin(spatial_dimension); Array<Real>::vector_iterator vend = vel_on_quad.end(spatial_dimension); Vector<Real> rho_v2(nb_quadrature_points); Real rho = materials[material_index(type)(index)]->getRho(); for (UInt q = 0; vit != vend; ++vit, ++q) { rho_v2(q) = rho * vit->dot(*vit); } AKANTU_DEBUG_OUT(); return .5 * getFEEngine().integrate(rho_v2, type, index); } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getExternalWork() { AKANTU_DEBUG_IN(); auto incr_or_velo_it = this->velocity->begin(spatial_dimension); if (this->method == _static) { incr_or_velo_it = this->displacement_increment->begin(spatial_dimension); } auto ext_force_it = external_force->begin(spatial_dimension); auto int_force_it = internal_force->begin(spatial_dimension); auto boun_it = blocked_dofs->begin(spatial_dimension); Real work = 0.; UInt nb_nodes = this->mesh.getNbNodes(); for (UInt n = 0; n < nb_nodes; ++n, ++ext_force_it, ++int_force_it, ++boun_it, ++incr_or_velo_it) { const auto & int_force = *int_force_it; const auto & ext_force = *ext_force_it; const auto & boun = *boun_it; const auto & incr_or_velo = *incr_or_velo_it; bool is_local_node = this->mesh.isLocalOrMasterNode(n); // bool is_not_pbc_slave_node = !this->isPBCSlaveNode(n); bool count_node = is_local_node; // && is_not_pbc_slave_node; if (count_node) { for (UInt i = 0; i < this->spatial_dimension; ++i) { if (boun(i)) work -= int_force(i) * incr_or_velo(i); else work += ext_force(i) * incr_or_velo(i); } } } StaticCommunicator::getStaticCommunicator().allReduce(work, _so_sum); if (this->method != _static) work *= this->getTimeStep(); AKANTU_DEBUG_OUT(); return work; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getEnergy(const std::string & energy_id) { AKANTU_DEBUG_IN(); if (energy_id == "kinetic") { return getKineticEnergy(); } else if (energy_id == "external work") { return getExternalWork(); } Real energy = 0.; for (auto & material : materials) energy += material->getEnergy(energy_id); /// reduction sum over all processors StaticCommunicator::getStaticCommunicator().allReduce(energy, _so_sum); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getEnergy(const std::string & energy_id, const ElementType & type, UInt index) { AKANTU_DEBUG_IN(); if (energy_id == "kinetic") { return getKineticEnergy(type, index); } UInt mat_index = this->material_index(type, _not_ghost)(index); UInt mat_loc_num = this->material_local_numbering(type, _not_ghost)(index); Real energy = this->materials[mat_index]->getEnergy(energy_id, type, mat_loc_num); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onElementsAdded(const Array<Element> & element_list, const NewElementsEvent & event) { AKANTU_DEBUG_IN(); this->getFEEngine().initShapeFunctions(_not_ghost); this->getFEEngine().initShapeFunctions(_ghost); for (auto ghost_type : ghost_types) { for (auto type : mesh.elementTypes(spatial_dimension, ghost_type, _ek_not_defined)) { UInt nb_element = this->mesh.getNbElement(type, ghost_type); if (!material_index.exists(type, ghost_type)) { this->material_index.alloc(nb_element, 1, type, ghost_type); this->material_local_numbering.alloc(nb_element, 1, type, ghost_type); } else { this->material_index(type, ghost_type).resize(nb_element); this->material_local_numbering(type, ghost_type).resize(nb_element); } } } ElementTypeMapArray<UInt> filter("new_element_filter", this->getID(), this->getMemoryID()); for (auto & elem : element_list) { if (!filter.exists(elem.type, elem.ghost_type)) filter.alloc(0, 1, elem.type, elem.ghost_type); filter(elem.type, elem.ghost_type).push_back(elem.element); } this->assignMaterialToElements(&filter); for (auto & material : materials) material->onElementsAdded(element_list, event); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onElementsRemoved( __attribute__((unused)) const Array<Element> & element_list, const ElementTypeMapArray<UInt> & new_numbering, const RemovedElementsEvent & event) { this->getFEEngine().initShapeFunctions(_not_ghost); this->getFEEngine().initShapeFunctions(_ghost); for (auto & material : materials) { material->onElementsRemoved(element_list, new_numbering, event); } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onNodesAdded(const Array<UInt> & nodes_list, __attribute__((unused)) const NewNodesEvent & event) { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); if (displacement) displacement->resize(nb_nodes, 0.); if (mass) mass->resize(nb_nodes, 0.); if (velocity) velocity->resize(nb_nodes, 0.); if (acceleration) acceleration->resize(nb_nodes, 0.); if (external_force) external_force->resize(nb_nodes, 0.); if (internal_force) internal_force->resize(nb_nodes, 0.); if (blocked_dofs) blocked_dofs->resize(nb_nodes, 0.); if (previous_displacement) previous_displacement->resize(nb_nodes, 0.); if (displacement_increment) displacement_increment->resize(nb_nodes, 0.); for (auto & material : materials) { material->onNodesAdded(nodes_list, event); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onNodesRemoved(__attribute__((unused)) const Array<UInt> & element_list, const Array<UInt> & new_numbering, __attribute__((unused)) const RemovedNodesEvent & event) { if (displacement) mesh.removeNodesFromArray(*displacement, new_numbering); if (mass) mesh.removeNodesFromArray(*mass, new_numbering); if (velocity) mesh.removeNodesFromArray(*velocity, new_numbering); if (acceleration) mesh.removeNodesFromArray(*acceleration, new_numbering); if (internal_force) mesh.removeNodesFromArray(*internal_force, new_numbering); if (external_force) mesh.removeNodesFromArray(*external_force, new_numbering); if (blocked_dofs) mesh.removeNodesFromArray(*blocked_dofs, new_numbering); // if (increment_acceleration) // mesh.removeNodesFromArray(*increment_acceleration, new_numbering); if (displacement_increment) mesh.removeNodesFromArray(*displacement_increment, new_numbering); if (previous_displacement) mesh.removeNodesFromArray(*previous_displacement, new_numbering); // if (method != _explicit_lumped_mass) { // this->initSolver(); // } } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::isInternal(const std::string & field_name, const ElementKind & element_kind) { /// check if at least one material contains field_id as an internal for (auto & material : materials) { bool is_internal = material->isInternal<Real>(field_name, element_kind); if (is_internal) return true; } return false; } /* -------------------------------------------------------------------------- */ ElementTypeMap<UInt> SolidMechanicsModel::getInternalDataPerElem(const std::string & field_name, const ElementKind & element_kind) { if (!(this->isInternal(field_name, element_kind))) AKANTU_EXCEPTION("unknown internal " << field_name); for (auto & material : materials) { if (material->isInternal<Real>(field_name, element_kind)) return material->getInternalDataPerElem<Real>(field_name, element_kind); } return ElementTypeMap<UInt>(); } /* -------------------------------------------------------------------------- */ ElementTypeMapArray<Real> & SolidMechanicsModel::flattenInternal(const std::string & field_name, const ElementKind & kind, const GhostType ghost_type) { std::pair<std::string, ElementKind> key(field_name, kind); if (this->registered_internals.count(key) == 0) { this->registered_internals[key] = new ElementTypeMapArray<Real>(field_name, this->id, this->memory_id); } ElementTypeMapArray<Real> * internal_flat = this->registered_internals[key]; for (auto type : mesh.elementTypes(spatial_dimension, ghost_type, kind)) { if (internal_flat->exists(type, ghost_type)) { auto & internal = (*internal_flat)(type, ghost_type); // internal.clear(); internal.resize(0); } } for (auto & material : materials) { if (material->isInternal<Real>(field_name, kind)) material->flattenInternal(field_name, *internal_flat, ghost_type, kind); } return *internal_flat; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::flattenAllRegisteredInternals( const ElementKind & kind) { ElementKind _kind; ID _id; for (auto & internal : this->registered_internals) { std::tie(_id, _kind) = internal.first; if (kind == _kind) this->flattenInternal(_id, kind); } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onDump() { this->flattenAllRegisteredInternals(_ek_regular); } /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER dumper::Field * SolidMechanicsModel::createElementalField( const std::string & field_name, const std::string & group_name, bool padding_flag, const UInt & spatial_dimension, const ElementKind & kind) { dumper::Field * field = NULL; if (field_name == "partitions") field = mesh.createElementalField<UInt, dumper::ElementPartitionField>( mesh.getConnectivities(), group_name, spatial_dimension, kind); else if (field_name == "material_index") field = mesh.createElementalField<UInt, Vector, dumper::ElementalField>( material_index, group_name, spatial_dimension, kind); else { // this copy of field_name is used to compute derivated data such as // strain and von mises stress that are based on grad_u and stress std::string field_name_copy(field_name); if (field_name == "strain" || field_name == "Green strain" || field_name == "principal strain" || field_name == "principal Green strain") field_name_copy = "grad_u"; else if (field_name == "Von Mises stress") field_name_copy = "stress"; bool is_internal = this->isInternal(field_name_copy, kind); if (is_internal) { ElementTypeMap<UInt> nb_data_per_elem = this->getInternalDataPerElem(field_name_copy, kind); ElementTypeMapArray<Real> & internal_flat = this->flattenInternal(field_name_copy, kind); field = mesh.createElementalField<Real, dumper::InternalMaterialField>( internal_flat, group_name, spatial_dimension, kind, nb_data_per_elem); if (field_name == "strain") { dumper::ComputeStrain<false> * foo = new dumper::ComputeStrain<false>(*this); field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); } else if (field_name == "Von Mises stress") { dumper::ComputeVonMisesStress * foo = new dumper::ComputeVonMisesStress(*this); field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); } else if (field_name == "Green strain") { dumper::ComputeStrain<true> * foo = new dumper::ComputeStrain<true>(*this); field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); } else if (field_name == "principal strain") { dumper::ComputePrincipalStrain<false> * foo = new dumper::ComputePrincipalStrain<false>(*this); field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); } else if (field_name == "principal Green strain") { dumper::ComputePrincipalStrain<true> * foo = new dumper::ComputePrincipalStrain<true>(*this); field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); } // treat the paddings if (padding_flag) { if (field_name == "stress") { if (spatial_dimension == 2) { dumper::StressPadder<2> * foo = new dumper::StressPadder<2>(*this); field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); } } else if (field_name == "strain" || field_name == "Green strain") { if (spatial_dimension == 2) { dumper::StrainPadder<2> * foo = new dumper::StrainPadder<2>(*this); field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); } } } // homogenize the field dumper::ComputeFunctorInterface * foo = dumper::HomogenizerProxy::createHomogenizer(*field); field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); } } return field; } /* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel::createNodalFieldReal(const std::string & field_name, const std::string & group_name, bool padding_flag) { std::map<std::string, Array<Real> *> real_nodal_fields; real_nodal_fields["displacement"] = this->displacement; real_nodal_fields["mass"] = this->mass; real_nodal_fields["velocity"] = this->velocity; real_nodal_fields["acceleration"] = this->acceleration; real_nodal_fields["external_force"] = this->external_force; real_nodal_fields["internal_force"] = this->internal_force; real_nodal_fields["increment"] = this->displacement_increment; if (field_name == "force") { AKANTU_EXCEPTION("The 'force' field has been renamed in 'external_force'"); } else if (field_name == "residual") { AKANTU_EXCEPTION( "The 'residual' field has been replaced by 'internal_force'"); } dumper::Field * field = NULL; if (padding_flag) field = this->mesh.createNodalField(real_nodal_fields[field_name], group_name, 3); else field = this->mesh.createNodalField(real_nodal_fields[field_name], group_name); return field; } /* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel::createNodalFieldBool( const std::string & field_name, const std::string & group_name, __attribute__((unused)) bool padding_flag) { std::map<std::string, Array<bool> *> uint_nodal_fields; uint_nodal_fields["blocked_dofs"] = blocked_dofs; dumper::Field * field = NULL; field = mesh.createNodalField(uint_nodal_fields[field_name], group_name); return field; } /* -------------------------------------------------------------------------- */ #else /* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel::createElementalField( __attribute__((unused)) const std::string & field_name, __attribute__((unused)) const std::string & group_name, __attribute__((unused)) bool padding_flag, __attribute__((unused)) const UInt & spatial_dimension, __attribute__((unused)) const ElementKind & kind) { return NULL; } /* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel::createNodalFieldReal( __attribute__((unused)) const std::string & field_name, __attribute__((unused)) const std::string & group_name, __attribute__((unused)) bool padding_flag) { return NULL; } /* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel::createNodalFieldBool( __attribute__((unused)) const std::string & field_name, __attribute__((unused)) const std::string & group_name, __attribute__((unused)) bool padding_flag) { return NULL; } #endif /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(const std::string & dumper_name) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); mesh.dump(dumper_name); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(const std::string & dumper_name, UInt step) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); mesh.dump(dumper_name, step); } /* ------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(const std::string & dumper_name, Real time, UInt step) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); mesh.dump(dumper_name, time, step); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump() { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); mesh.dump(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(UInt step) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); mesh.dump(step); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(Real time, UInt step) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); mesh.dump(time, step); } /* -------------------------------------------------------------------------- */ 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; getFEEngine().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); external_force->printself(stream, indent + 2); internal_force->printself(stream, indent + 2); blocked_dofs->printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + material information [" << std::endl; material_index.printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + materials [" << std::endl; for (auto & material : materials) { material->printself(stream, indent + 1); } stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/solid_mechanics_model.hh b/src/model/solid_mechanics/solid_mechanics_model.hh index 1f885d1a8..ff11bb0e2 100644 --- a/src/model/solid_mechanics/solid_mechanics_model.hh +++ b/src/model/solid_mechanics/solid_mechanics_model.hh @@ -1,814 +1,814 @@ /** * @file solid_mechanics_model.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Jul 27 2010 * @date last modification: Tue Jan 19 2016 * * @brief Model of Solid Mechanics * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLID_MECHANICS_MODEL_HH__ #define __AKANTU_SOLID_MECHANICS_MODEL_HH__ /* -------------------------------------------------------------------------- */ #include <fstream> /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_named_argument.hh" #include "aka_types.hh" #include "boundary_condition.hh" #include "data_accessor.hh" #include "dumpable.hh" #include "integrator_gauss.hh" #include "material_selector.hh" #include "mesh.hh" #include "model.hh" #include "shape_lagrange.hh" #include "solid_mechanics_model_event_handler.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class Material; class DumperIOHelper; class NonLocalManager; } // namespace akantu /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { DECLARE_NAMED_ARGUMENT(analysis_method); DECLARE_NAMED_ARGUMENT(no_init_materials); struct SolidMechanicsModelOptions : public ModelOptions { SolidMechanicsModelOptions(AnalysisMethod analysis_method = _explicit_lumped_mass, bool no_init_materials = false) : analysis_method(analysis_method), no_init_materials(no_init_materials) { } template <typename... pack> SolidMechanicsModelOptions(use_named_args_t, pack &&... _pack) : SolidMechanicsModelOptions( OPTIONAL_NAMED_ARG(analysis_method, _explicit_lumped_mass), OPTIONAL_NAMED_ARG(no_init_materials, false)) {} AnalysisMethod analysis_method; bool no_init_materials; }; extern const SolidMechanicsModelOptions default_solid_mechanics_model_options; class SolidMechanicsModel : public Model, public DataAccessor<Element>, public DataAccessor<UInt>, public MeshEventHandler, public BoundaryCondition<SolidMechanicsModel>, public EventHandlerManager<SolidMechanicsModelEventHandler> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: class NewMaterialElementsEvent : public NewElementsEvent { public: AKANTU_GET_MACRO_NOT_CONST(MaterialList, material, Array<UInt> &); AKANTU_GET_MACRO(MaterialList, material, const Array<UInt> &); protected: Array<UInt> material; }; typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange> MyFEEngineType; protected: typedef EventHandlerManager<SolidMechanicsModelEventHandler> EventManager; public: SolidMechanicsModel(Mesh & mesh, UInt spatial_dimension = _all_dimensions, const ID & id = "solid_mechanics_model", const MemoryID & memory_id = 0); virtual ~SolidMechanicsModel(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: template <typename P, typename T, typename... pack> void initFull(named_argument::param_t<P, T &&> && first, pack &&... _pack) { this->initFull(SolidMechanicsModelOptions{use_named_args, first, _pack...}); } /// initialize completely the model void initFull(const ModelOptions & options = SolidMechanicsModelOptions()) override; /// initialize the fem object needed for boundary conditions void initFEEngineBoundary(); /// register the tags associated with the parallel synchronizer // virtual void initParallel(MeshPartition * partition, // DataAccessor<Element> * data_accessor = NULL); /// allocate all vectors virtual void initArrays(); /// allocate all vectors // void initArraysPreviousDisplacment(); /// initialize all internal arrays for materials virtual void initMaterials(); /// initialize the model virtual void initModel(); /// init PBC synchronizer // void initPBC(); /// initialize a new solver and sets it as the default one to use void initNewSolver(const AnalysisMethod & method); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; protected: /// allocate an array if needed template <typename T> void allocNodalField(Array<T> *& array, UInt nb_component, const ID & name); /* ------------------------------------------------------------------------ */ /* PBC */ /* ------------------------------------------------------------------------ */ public: /// change the equation number for proper assembly when using PBC // void changeEquationNumberforPBC(std::map <UInt, UInt> & pbc_pair); /// synchronize Residual for output // void synchronizeResidual(); protected: /// register PBC synchronizer // void registerPBCSynchronizer(); /* ------------------------------------------------------------------------ */ /* Solver interface */ /* ------------------------------------------------------------------------ */ public: /// assembles the stiffness matrix, virtual void assembleStiffnessMatrix(); /// assembles the internal forces in the array internal_forces virtual void assembleInternalForces(); protected: /// callback for the solver, this adds f_{ext} - f_{int} to the residual void assembleResidual() override; /// callback for the solver, this assembles the stiffness matrix void assembleJacobian() override; /// callback for the solver, this is called at beginning of solve void predictor() override; /// callback for the solver, this is called at end of solve void corrector() override; /// Callback for the model to instantiate the matricees when needed void initSolver(TimeStepSolverType time_step_solver_type, NonLinearSolverType non_linear_solver_type) override; protected: /* ------------------------------------------------------------------------ */ TimeStepSolverType getDefaultSolverType() const override; /* ------------------------------------------------------------------------ */ ModelSolverOptions getDefaultSolverOptions(const TimeStepSolverType & type) const override; /* ------------------------------------------------------------------------ */ /* Explicit */ /* ------------------------------------------------------------------------ */ // public: // /// initialize the stuff for the explicit scheme // void initExplicit(AnalysisMethod analysis_method = // _explicit_lumped_mass); // bool isExplicit() { // return method == _explicit_lumped_mass || // method == _explicit_consistent_mass; // } // /// 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 // virtual void updateResidual(bool need_initialize = true); // /** // * \brief compute the acceleration from the residual // * this function is the explicit equivalent to solveDynamic in implicit // * In the case of lumped mass just divide the residual by the mass // * In the case of not lumped mass call // solveDynamic<_acceleration_corrector> // */ // void updateAcceleration(); /// Update the increment of displacement // void updateIncrement(); // /// Copy the actuel displacement into previous displacement // void updatePreviousDisplacement(); // /// Save stress and strain through EventManager // void saveStressAndStrainBeforeDamage(); // /// Update energies through EventManager // void updateEnergiesAfterDamage(); // /// Solve the system @f[ A x = \alpha b @f] with A a lumped matrix // void solveLumped(Array<Real> & x, const Array<Real> & A, // const Array<Real> & b, const Array<bool> & blocked_dofs, // Real alpha); // /// explicit integration predictor // void explicitPred(); // /// explicit integration corrector // void explicitCorr(); // public: // void solveStep(); // /* // ------------------------------------------------------------------------ // */ // /* Implicit */ // /* // ------------------------------------------------------------------------ // */ // public: // /// initialize the solver and the jacobian_matrix (called by // initImplicit) // void initSolver(); // /// 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(); // public: // /** // * solve a step (predictor + convergence loop + corrector) using the // * the given convergence method (see akantu::SolveConvergenceMethod) // * and the given convergence criteria (see // * akantu::SolveConvergenceCriteria) // **/ // template <SolveConvergenceMethod method, SolveConvergenceCriteria // criteria> // bool solveStep(Real tolerance, UInt max_iteration = 100); // template <SolveConvergenceMethod method, SolveConvergenceCriteria // criteria> // bool solveStep(Real tolerance, Real & error, UInt max_iteration = 100, // bool do_not_factorize = false); // public: // /** // * solve Ku = f using the the given convergence method (see // * akantu::SolveConvergenceMethod) and the given convergence // * criteria (see akantu::SolveConvergenceCriteria) // **/ // template <SolveConvergenceMethod cmethod, SolveConvergenceCriteria // criteria> // bool solveStatic(Real tolerance, UInt max_iteration, // bool do_not_factorize = false); // /// create and return the velocity damping matrix // SparseMatrix & initVelocityDampingMatrix(); // /// implicit time integration predictor // void implicitPred(); // /// implicit time integration corrector // void implicitCorr(); // /// compute the Cauchy stress on user demand. // void computeCauchyStresses(); // // /// compute A and solve @f[ A\delta u = f_ext - f_int @f] // // template <NewmarkBeta::IntegrationSchemeCorrectorType type> // // void solve(Array<Real> &increment, Real block_val = 1., // // bool need_factorize = true, bool has_profile_changed = // false); // protected: // /// finish the computation of residual to solve in increment // void updateResidualInternal(); // /// compute the support reaction and store it in force // void updateSupportReaction(); // private: // /// re-initialize the J matrix (to use if the profile of K changed) // void initJacobianMatrix(); /* ------------------------------------------------------------------------ */ void updateDataForNonLocalCriterion(ElementTypeMapReal & criterion) override; // public: /// Update the stresses for the computation of the residual of the Stiffness /// matrix in the case of finite deformation // void computeStresses(); /// synchronize the ghost element boundaries values // void synchronizeBoundaries(); /* ------------------------------------------------------------------------ */ /* Materials (solid_mechanics_model_material.cc) */ /* ------------------------------------------------------------------------ */ public: /// registers all the custom materials of a given type present in the input /// file template <typename M> void registerNewCustomMaterials(const ID & mat_type); /// register an empty material of a given type template <typename M> Material & registerNewEmptyMaterial(const std::string & name); // /// Use a UIntData in the mesh to specify the material to use per element // void setMaterialIDsFromIntData(const std::string & data_name); /// reassigns materials depending on the material selector virtual void reassignMaterial(); /// apply a constant eigen_grad_u on all quadrature points of a given material virtual void applyEigenGradU(const Matrix<Real> & prescribed_eigen_grad_u, const ID & material_name, const GhostType ghost_type = _not_ghost); protected: /// register a material in the dynamic database template <typename M> Material & registerNewMaterial(const ParserSection & mat_section); /// read the material files to instantiate all the materials void instantiateMaterials(); /// set the element_id_by_material and add the elements to the good materials void assignMaterialToElements(const ElementTypeMapArray<UInt> * filter = NULL); /// reinitialize dof_synchronizer and solver (either in implicit or /// explicit) when cohesive elements are inserted void reinitializeSolver(); /* ------------------------------------------------------------------------ */ /* Mass (solid_mechanics_model_mass.cc) */ /* ------------------------------------------------------------------------ */ public: /// assemble the lumped mass matrix void assembleMassLumped(); /// assemble the mass matrix for consistent mass resolutions void assembleMass(); protected: /// assemble the lumped mass matrix for local and ghost elements void assembleMassLumped(GhostType ghost_type); /// assemble the mass matrix for either _ghost or _not_ghost elements void assembleMass(GhostType ghost_type); /// fill a vector of rho void computeRho(Array<Real> & rho, ElementType type, GhostType ghost_type); /// compute the kinetic energy Real getKineticEnergy(); Real getKineticEnergy(const ElementType & type, UInt index); /// compute the external work (for impose displacement, the velocity should be /// given too) Real getExternalWork(); /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ public: inline UInt getNbData(const Array<Element> & elements, const SynchronizationTag & tag) const override; inline void packData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) const override; inline void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) override; inline UInt getNbData(const Array<UInt> & dofs, const SynchronizationTag & tag) const override; inline void packData(CommunicationBuffer & buffer, const Array<UInt> & dofs, const SynchronizationTag & tag) const override; inline void unpackData(CommunicationBuffer & buffer, const Array<UInt> & dofs, const SynchronizationTag & tag) override; protected: inline void splitElementByMaterial(const Array<Element> & elements, Array<Element> * elements_per_mat) const; /* ------------------------------------------------------------------------ */ /* Mesh Event Handler inherited members */ /* ------------------------------------------------------------------------ */ protected: void onNodesAdded(const Array<UInt> & nodes_list, const NewNodesEvent & event) override; void onNodesRemoved(const Array<UInt> & element_list, const Array<UInt> & new_numbering, const RemovedNodesEvent & event) override; void onElementsAdded(const Array<Element> & nodes_list, const NewElementsEvent & event) override; void onElementsRemoved(const Array<Element> & element_list, const ElementTypeMapArray<UInt> & new_numbering, const RemovedElementsEvent & event) override; void onElementsChanged(const Array<Element> &, const Array<Element> &, const ElementTypeMapArray<UInt> &, const ChangedElementsEvent &) override{}; /* ------------------------------------------------------------------------ */ /* Dumpable interface (kept for convenience) and dumper relative functions */ /* ------------------------------------------------------------------------ */ public: virtual void onDump(); //! decide wether a field is a material internal or not bool isInternal(const std::string & field_name, const ElementKind & element_kind); #ifndef SWIG //! give the amount of data per element virtual ElementTypeMap<UInt> getInternalDataPerElem(const std::string & field_name, const ElementKind & kind); //! flatten a given material internal field ElementTypeMapArray<Real> & flattenInternal(const std::string & field_name, const ElementKind & kind, const GhostType ghost_type = _not_ghost); //! flatten all the registered material internals void flattenAllRegisteredInternals(const ElementKind & kind); #endif dumper::Field * createNodalFieldReal(const std::string & field_name, const std::string & group_name, bool padding_flag) override; dumper::Field * createNodalFieldBool(const std::string & field_name, const std::string & group_name, bool padding_flag) override; dumper::Field * createElementalField(const std::string & field_name, const std::string & group_name, bool padding_flag, const UInt & spatial_dimension, const ElementKind & kind) override; virtual void dump(const std::string & dumper_name); virtual void dump(const std::string & dumper_name, UInt step); virtual void dump(const std::string & dumper_name, Real time, UInt step); void dump() override; virtual void dump(UInt step); virtual void dump(Real time, UInt step); /* ------------------------------------------------------------------------ */ /* 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 void setTimeStep(Real time_step, const ID & solver_id = "") override; /// void setTimeStep(Real time_step); /// return the of iterations done in the last solveStep // AKANTU_GET_MACRO(NumberIter, n_iter, UInt); /// 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, Array<Real> &); /// get the SolidMechanicsModel::previous_displacement vector AKANTU_GET_MACRO(PreviousDisplacement, *previous_displacement, Array<Real> &); /// get the SolidMechanicsModel::current_position vector \warn only consistent /// after a call to SolidMechanicsModel::updateCurrentPosition AKANTU_GET_MACRO(CurrentPosition, *current_position, const Array<Real> &); /// get the SolidMechanicsModel::increment vector \warn only consistent if /// SolidMechanicsModel::setIncrementFlagOn has been called before AKANTU_GET_MACRO(Increment, *displacement_increment, Array<Real> &); /// get the lumped SolidMechanicsModel::mass vector AKANTU_GET_MACRO(Mass, *mass, Array<Real> &); /// get the SolidMechanicsModel::velocity vector AKANTU_GET_MACRO(Velocity, *velocity, Array<Real> &); /// get the SolidMechanicsModel::acceleration vector, updated by /// SolidMechanicsModel::updateAcceleration AKANTU_GET_MACRO(Acceleration, *acceleration, Array<Real> &); /// get the SolidMechanicsModel::force vector (external forces) AKANTU_GET_MACRO(Force, *external_force, Array<Real> &); /// get the SolidMechanicsModel::internal_force vector (internal forces) AKANTU_GET_MACRO(InternalForce, *internal_force, Array<Real> &); /// get the SolidMechanicsModel::blocked_dofs vector AKANTU_GET_MACRO(BlockedDOFs, *blocked_dofs, Array<bool> &); /// get the SolidMechnicsModel::incrementAcceleration vector // AKANTU_GET_MACRO(IncrementAcceleration, *increment_acceleration, // Array<Real> &); /// get the value of the SolidMechanicsModel::increment_flag AKANTU_GET_MACRO(IncrementFlag, increment_flag, bool); /// get a particular material (by material index) inline Material & getMaterial(UInt mat_index); /// get a particular material (by material index) inline const Material & getMaterial(UInt mat_index) const; /// get a particular material (by material name) inline Material & getMaterial(const std::string & name); /// get a particular material (by material name) inline const Material & getMaterial(const std::string & name) const; /// get a particular material id from is name inline UInt getMaterialIndex(const std::string & name) const; /// give the number of materials inline UInt getNbMaterials() const { return materials.size(); } inline void setMaterialSelector(MaterialSelector & selector); /// give the material internal index from its id Int getInternalIndexFromID(const ID & id) const; /// compute the stable time step Real getStableTimeStep(); /// get the energies Real getEnergy(const std::string & energy_id); /// compute the energy for energy Real getEnergy(const std::string & energy_id, const ElementType & type, UInt index); /** * @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 global jacobian matrix of the system // AKANTU_GET_MACRO(GlobalJacobianMatrix, *jacobian_matrix, const SparseMatrix // &); // /// get the mass matrix // AKANTU_GET_MACRO(MassMatrix, *mass_matrix, SparseMatrix &); // /// get the velocity damping matrix // AKANTU_GET_MACRO(VelocityDampingMatrix, *velocity_damping_matrix, // SparseMatrix &); /// get the FEEngine object to integrate or interpolate on the boundary inline FEEngine & getFEEngineBoundary(const ID & name = ""); // /// get integrator // AKANTU_GET_MACRO(Integrator, *integrator, const IntegrationScheme2ndOrder // &); // /// get synchronizer // AKANTU_GET_MACRO(Synchronizer, *synch_parallel, const ElementSynchronizer // &); AKANTU_GET_MACRO(MaterialByElement, material_index, const ElementTypeMapArray<UInt> &); /// vectors containing local material element index for each global element /// index AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialByElement, material_index, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialByElement, material_index, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialLocalNumbering, material_local_numbering, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialLocalNumbering, material_local_numbering, UInt); /// Get the type of analysis method used AKANTU_GET_MACRO(AnalysisMethod, method, AnalysisMethod); /// get the non-local manager AKANTU_GET_MACRO(NonLocalManager, *non_local_manager, NonLocalManager &); protected: friend class Material; protected: /// compute the stable time step Real getStableTimeStep(const GhostType & ghost_type); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// number of iterations // UInt n_iter; /// time step // Real time_step; /// conversion coefficient form force/mass to acceleration Real f_m2a; /// displacements array Array<Real> * displacement; /// displacements array at the previous time step (used in finite deformation) Array<Real> * previous_displacement; /// increment of displacement Array<Real> * displacement_increment; /// lumped mass array Array<Real> * mass; /// velocities array Array<Real> * velocity; /// accelerations array Array<Real> * acceleration; /// accelerations array // Array<Real> * increment_acceleration; /// external forces array Array<Real> * external_force; /// internal forces array Array<Real> * internal_force; /// array specifing if a degree of freedom is blocked or not Array<bool> * blocked_dofs; /// array of current position used during update residual Array<Real> * 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; /// Arrays containing the material index for each element ElementTypeMapArray<UInt> material_index; /// Arrays containing the position in the element filter of the material /// (material's local numbering) ElementTypeMapArray<UInt> material_local_numbering; #ifdef SWIGPYTHON public: #endif /// list of used materials std::vector<std::unique_ptr<Material>> materials; /// mapping between material name and material internal id std::map<std::string, UInt> materials_names_to_id; #ifdef SWIGPYTHON protected: #endif /// class defining of to choose a material MaterialSelector * material_selector; /// define if it is the default selector or not bool is_default_material_selector; // /// integration scheme of second order used // IntegrationScheme2ndOrder *integrator; /// flag defining if the increment must be computed or not bool increment_flag; /// analysis method check the list in akantu::AnalysisMethod AnalysisMethod method; /// tells if the material are instantiated bool are_materials_instantiated; typedef std::map<std::pair<std::string, ElementKind>, ElementTypeMapArray<Real> *> flatten_internal_map; /// map a registered internals to be flattened for dump purposes flatten_internal_map registered_internals; /// pointer to non-local manager: For non-local continuum damage computations NonLocalManager * non_local_manager; /// pointer to the pbc synchronizer // PBCSynchronizer * pbc_synch; }; /* -------------------------------------------------------------------------- */ namespace BC { namespace Neumann { typedef FromHigherDim FromStress; typedef FromSameDim FromTraction; } // namespace Neumann } // namespace BC -__END_AKANTU__ +} // akantu /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material.hh" #include "parser.hh" -__BEGIN_AKANTU__ +namespace akantu { #include "solid_mechanics_model_inline_impl.cc" #include "solid_mechanics_model_tmpl.hh" /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const SolidMechanicsModel & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #include "material_selector_tmpl.hh" #endif /* __AKANTU_SOLID_MECHANICS_MODEL_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.cc index 11c6bf67a..bb191635c 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.cc @@ -1,650 +1,650 @@ /** * @file fragment_manager.cc * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Thu Jan 23 2014 * @date last modification: Mon Dec 14 2015 * * @brief Group manager to handle fragments * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "fragment_manager.hh" #include "material_cohesive.hh" #include <numeric> #include <algorithm> #include <functional> -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ FragmentManager::FragmentManager(SolidMechanicsModelCohesive & model, bool dump_data, const ID & id, const MemoryID & memory_id) : GroupManager(model.getMesh(), id, memory_id), model(model), mass_center(0, model.getSpatialDimension(), "mass_center"), mass(0, model.getSpatialDimension(), "mass"), velocity(0, model.getSpatialDimension(), "velocity"), inertia_moments(0, model.getSpatialDimension(), "inertia_moments"), principal_directions(0, model.getSpatialDimension() * model.getSpatialDimension(), "principal_directions"), quad_coordinates("quad_coordinates", id), mass_density("mass_density", id), nb_elements_per_fragment(0, 1, "nb_elements_per_fragment"), dump_data(dump_data) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); /// compute quadrature points' coordinates mesh.initElementTypeMapArray(quad_coordinates, spatial_dimension, spatial_dimension, _not_ghost); model.getFEEngine().interpolateOnIntegrationPoints(model.getMesh().getNodes(), quad_coordinates); /// store mass density per quadrature point mesh.initElementTypeMapArray(mass_density, 1, spatial_dimension, _not_ghost); storeMassDensityPerIntegrationPoint(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ class CohesiveElementFilter : public GroupManager::ClusteringFilter { public: CohesiveElementFilter(const SolidMechanicsModelCohesive & model, const Real max_damage = 1.) : model(model), is_unbroken(max_damage) {} bool operator() (const Element & el) const { if (el.kind == _ek_regular) return true; const Array<UInt> & mat_indexes = model.getMaterialByElement(el.type, el.ghost_type); const Array<UInt> & mat_loc_num = model.getMaterialLocalNumbering(el.type, el.ghost_type); const MaterialCohesive & mat = static_cast<const MaterialCohesive &> (model.getMaterial(mat_indexes(el.element))); UInt el_index = mat_loc_num(el.element); UInt nb_quad_per_element = model.getFEEngine("CohesiveFEEngine").getNbIntegrationPoints(el.type, el.ghost_type); const Array<Real> & damage_array = mat.getDamage(el.type, el.ghost_type); AKANTU_DEBUG_ASSERT(nb_quad_per_element * el_index < damage_array.getSize(), "This quadrature point is out of range"); const Real * element_damage = damage_array.storage() + nb_quad_per_element * el_index; UInt unbroken_quads = std::count_if(element_damage, element_damage + nb_quad_per_element, is_unbroken); if (unbroken_quads > 0) return true; return false; } private: struct IsUnbrokenFunctor { IsUnbrokenFunctor(const Real & max_damage) : max_damage(max_damage) {} bool operator() (const Real & x) {return x < max_damage;} const Real max_damage; }; const SolidMechanicsModelCohesive & model; const IsUnbrokenFunctor is_unbroken; }; /* -------------------------------------------------------------------------- */ void FragmentManager::buildFragments(Real damage_limit) { AKANTU_DEBUG_IN(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) ElementSynchronizer * cohesive_synchronizer = const_cast<ElementSynchronizer *>(model.getCohesiveSynchronizer()); if (cohesive_synchronizer) { cohesive_synchronizer->computeBufferSize(model, _gst_smmc_damage); cohesive_synchronizer->asynchronousSynchronize(model, _gst_smmc_damage); cohesive_synchronizer->waitEndSynchronize(model, _gst_smmc_damage); } #endif ElementSynchronizer & synchronizer = const_cast<ElementSynchronizer &>(model.getSynchronizer()); Mesh & mesh_facets = const_cast<Mesh &>(mesh.getMeshFacets()); UInt spatial_dimension = model.getSpatialDimension(); std::string fragment_prefix("fragment"); /// generate fragments global_nb_fragment = createClusters(spatial_dimension, fragment_prefix, CohesiveElementFilter(model, damage_limit), &synchronizer, &mesh_facets); nb_fragment = getNbElementGroups(spatial_dimension); fragment_index.resize(nb_fragment); UInt * fragment_index_it = fragment_index.storage(); /// loop over fragments for(const_element_group_iterator it(element_group_begin()); it != element_group_end(); ++it, ++fragment_index_it) { /// get fragment index std::string fragment_index_string = it->first.substr(fragment_prefix.size() + 1); std::stringstream sstr(fragment_index_string.c_str()); sstr >> *fragment_index_it; AKANTU_DEBUG_ASSERT(!sstr.fail(), "fragment_index is not an integer"); } /// compute fragments' mass computeMass(); if (dump_data) { createDumpDataArray(fragment_index, "fragments", true); createDumpDataArray(mass, "fragments mass"); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FragmentManager::computeMass() { AKANTU_DEBUG_IN(); UInt spatial_dimension = model.getSpatialDimension(); /// create a unit field per quadrature point, since to compute mass /// it's neccessary to integrate only density ElementTypeMapArray<Real> unit_field("unit_field", id); mesh.initElementTypeMapArray(unit_field, spatial_dimension, spatial_dimension, _not_ghost); ElementTypeMapArray<Real>::type_iterator it = unit_field.firstType(spatial_dimension, _not_ghost, _ek_regular); ElementTypeMapArray<Real>::type_iterator end = unit_field.lastType(spatial_dimension, _not_ghost, _ek_regular); for (; it != end; ++it) { ElementType type = *it; Array<Real> & field_array = unit_field(type); UInt nb_element = mesh.getNbElement(type); UInt nb_quad_per_element = model.getFEEngine().getNbIntegrationPoints(type); field_array.resize(nb_element * nb_quad_per_element); field_array.set(1.); } integrateFieldOnFragments(unit_field, mass); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FragmentManager::computeCenterOfMass() { AKANTU_DEBUG_IN(); /// integrate position multiplied by density integrateFieldOnFragments(quad_coordinates, mass_center); /// divide it by the fragments' mass Real * mass_storage = mass.storage(); Real * mass_center_storage = mass_center.storage(); UInt total_components = mass_center.getSize() * mass_center.getNbComponent(); for (UInt i = 0; i < total_components; ++i) mass_center_storage[i] /= mass_storage[i]; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FragmentManager::computeVelocity() { AKANTU_DEBUG_IN(); UInt spatial_dimension = model.getSpatialDimension(); /// compute velocity per quadrature point ElementTypeMapArray<Real> velocity_field("velocity_field", id); mesh.initElementTypeMapArray(velocity_field, spatial_dimension, spatial_dimension, _not_ghost); model.getFEEngine().interpolateOnIntegrationPoints(model.getVelocity(), velocity_field); /// integrate on fragments integrateFieldOnFragments(velocity_field, velocity); /// divide it by the fragments' mass Real * mass_storage = mass.storage(); Real * velocity_storage = velocity.storage(); UInt total_components = velocity.getSize() * velocity.getNbComponent(); for (UInt i = 0; i < total_components; ++i) velocity_storage[i] /= mass_storage[i]; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Given the distance @f$ \mathbf{r} @f$ between a quadrature point * and its center of mass, the moment of inertia is computed as \f[ * I_\mathrm{CM} = \mathrm{tr}(\mathbf{r}\mathbf{r}^\mathrm{T}) * \mathbf{I} - \mathbf{r}\mathbf{r}^\mathrm{T} \f] for more * information check Wikipedia * (http://en.wikipedia.org/wiki/Moment_of_inertia#Identities_for_a_skew-symmetric_matrix) * */ void FragmentManager::computeInertiaMoments() { AKANTU_DEBUG_IN(); UInt spatial_dimension = model.getSpatialDimension(); computeCenterOfMass(); /// compute local coordinates products with respect to the center of match ElementTypeMapArray<Real> moments_coords("moments_coords", id); mesh.initElementTypeMapArray(moments_coords, spatial_dimension * spatial_dimension, spatial_dimension, _not_ghost); /// resize the by element type ElementTypeMapArray<Real>::type_iterator it = moments_coords.firstType(spatial_dimension, _not_ghost, _ek_regular); ElementTypeMapArray<Real>::type_iterator end = moments_coords.lastType(spatial_dimension, _not_ghost, _ek_regular); for (; it != end; ++it) { ElementType type = *it; Array<Real> & field_array = moments_coords(type); UInt nb_element = mesh.getNbElement(type); UInt nb_quad_per_element = model.getFEEngine().getNbIntegrationPoints(type); field_array.resize(nb_element * nb_quad_per_element); } /// compute coordinates Array<Real>::const_vector_iterator mass_center_it = mass_center.begin(spatial_dimension); /// loop over fragments for(const_element_group_iterator it(element_group_begin()); it != element_group_end(); ++it, ++mass_center_it) { const ElementTypeMapArray<UInt> & el_list = it->second->getElements(); ElementTypeMapArray<UInt>::type_iterator type_it = el_list.firstType(spatial_dimension, _not_ghost, _ek_regular); ElementTypeMapArray<UInt>::type_iterator type_end = el_list.lastType(spatial_dimension, _not_ghost, _ek_regular); /// loop over elements of the fragment for (; type_it != type_end; ++type_it) { ElementType type = *type_it; UInt nb_quad_per_element = model.getFEEngine().getNbIntegrationPoints(type); Array<Real> & moments_coords_array = moments_coords(type); const Array<Real> & quad_coordinates_array = quad_coordinates(type); const Array<UInt> & el_list_array = el_list(type); Array<Real>::matrix_iterator moments_begin = moments_coords_array.begin(spatial_dimension, spatial_dimension); Array<Real>::const_vector_iterator quad_coordinates_begin = quad_coordinates_array.begin(spatial_dimension); Vector<Real> relative_coords(spatial_dimension); for (UInt el = 0; el < el_list_array.getSize(); ++el) { UInt global_el = el_list_array(el); /// loop over quadrature points for (UInt q = 0; q < nb_quad_per_element; ++q) { UInt global_q = global_el * nb_quad_per_element + q; Matrix<Real> moments_matrix = moments_begin[global_q]; const Vector<Real> & quad_coord_vector = quad_coordinates_begin[global_q]; /// to understand this read the documentation written just /// before this function relative_coords = quad_coord_vector; relative_coords -= *mass_center_it; moments_matrix.outerProduct(relative_coords, relative_coords); Real trace = moments_matrix.trace(); moments_matrix *= -1.; moments_matrix += Matrix<Real>::eye(spatial_dimension, trace); } } } } /// integrate moments Array<Real> integrated_moments(global_nb_fragment, spatial_dimension * spatial_dimension); integrateFieldOnFragments(moments_coords, integrated_moments); /// compute and store principal moments inertia_moments.resize(global_nb_fragment); principal_directions.resize(global_nb_fragment); Array<Real>::matrix_iterator integrated_moments_it = integrated_moments.begin(spatial_dimension, spatial_dimension); Array<Real>::vector_iterator inertia_moments_it = inertia_moments.begin(spatial_dimension); Array<Real>::matrix_iterator principal_directions_it = principal_directions.begin(spatial_dimension, spatial_dimension); for (UInt frag = 0; frag < global_nb_fragment; ++frag, ++integrated_moments_it, ++inertia_moments_it, ++principal_directions_it) { integrated_moments_it->eig(*inertia_moments_it, *principal_directions_it); } if (dump_data) createDumpDataArray(inertia_moments, "moments of inertia"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FragmentManager::computeAllData() { AKANTU_DEBUG_IN(); buildFragments(); computeVelocity(); computeInertiaMoments(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FragmentManager::storeMassDensityPerIntegrationPoint() { AKANTU_DEBUG_IN(); UInt spatial_dimension = model.getSpatialDimension(); Mesh::type_iterator it = mesh.firstType(spatial_dimension); Mesh::type_iterator end = mesh.lastType(spatial_dimension); for (; it != end; ++it) { ElementType type = *it; Array<Real> & mass_density_array = mass_density(type); UInt nb_element = mesh.getNbElement(type); UInt nb_quad_per_element = model.getFEEngine().getNbIntegrationPoints(type); mass_density_array.resize(nb_element * nb_quad_per_element); const Array<UInt> & mat_indexes = model.getMaterialByElement(type); Real * mass_density_it = mass_density_array.storage(); /// store mass_density for each element and quadrature point for (UInt el = 0; el < nb_element; ++el) { Material & mat = model.getMaterial(mat_indexes(el)); for (UInt q = 0; q < nb_quad_per_element; ++q, ++mass_density_it) *mass_density_it = mat.getRho(); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FragmentManager::integrateFieldOnFragments(ElementTypeMapArray<Real> & field, Array<Real> & output) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model.getSpatialDimension(); UInt nb_component = output.getNbComponent(); /// integration part output.resize(global_nb_fragment); output.clear(); UInt * fragment_index_it = fragment_index.storage(); Array<Real>::vector_iterator output_begin = output.begin(nb_component); /// loop over fragments for(const_element_group_iterator it(element_group_begin()); it != element_group_end(); ++it, ++fragment_index_it) { const ElementTypeMapArray<UInt> & el_list = it->second->getElements(); ElementTypeMapArray<UInt>::type_iterator type_it = el_list.firstType(spatial_dimension, _not_ghost, _ek_regular); ElementTypeMapArray<UInt>::type_iterator type_end = el_list.lastType(spatial_dimension, _not_ghost, _ek_regular); /// loop over elements of the fragment for (; type_it != type_end; ++type_it) { ElementType type = *type_it; UInt nb_quad_per_element = model.getFEEngine().getNbIntegrationPoints(type); const Array<Real> & density_array = mass_density(type); Array<Real> & field_array = field(type); const Array<UInt> & elements = el_list(type); UInt nb_element = elements.getSize(); /// generate array to be integrated by filtering fragment's elements Array<Real> integration_array(elements.getSize() * nb_quad_per_element, nb_component); Array<Real>::matrix_iterator int_array_it = integration_array.begin_reinterpret(nb_quad_per_element, nb_component, nb_element); Array<Real>::matrix_iterator int_array_end = integration_array.end_reinterpret(nb_quad_per_element, nb_component, nb_element); Array<Real>::matrix_iterator field_array_begin = field_array.begin_reinterpret(nb_quad_per_element, nb_component, field_array.getSize() / nb_quad_per_element); Array<Real>::const_vector_iterator density_array_begin = density_array.begin_reinterpret(nb_quad_per_element, density_array.getSize() / nb_quad_per_element); for (UInt el = 0; int_array_it != int_array_end; ++int_array_it, ++el) { UInt global_el = elements(el); *int_array_it = field_array_begin[global_el]; /// multiply field by density const Vector<Real> & density_vector = density_array_begin[global_el]; for (UInt i = 0; i < nb_quad_per_element; ++i) { for (UInt j = 0; j < nb_component; ++j) { (*int_array_it)(i, j) *= density_vector(i); } } } /// integrate the field over the fragment Array<Real> integrated_array(elements.getSize(), nb_component); model.getFEEngine().integrate(integration_array, integrated_array, nb_component, type, _not_ghost, elements); /// sum over all elements and store the result Vector<Real> output_tmp(output_begin[*fragment_index_it]); output_tmp += std::accumulate(integrated_array.begin(nb_component), integrated_array.end(nb_component), Vector<Real>(nb_component)); } } /// sum output over all processors StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); comm.allReduce(output.storage(), global_nb_fragment * nb_component, _so_sum); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FragmentManager::computeNbElementsPerFragment() { AKANTU_DEBUG_IN(); UInt spatial_dimension = model.getSpatialDimension(); nb_elements_per_fragment.resize(global_nb_fragment); nb_elements_per_fragment.clear(); UInt * fragment_index_it = fragment_index.storage(); /// loop over fragments for(const_element_group_iterator it(element_group_begin()); it != element_group_end(); ++it, ++fragment_index_it) { const ElementTypeMapArray<UInt> & el_list = it->second->getElements(); ElementTypeMapArray<UInt>::type_iterator type_it = el_list.firstType(spatial_dimension, _not_ghost, _ek_regular); ElementTypeMapArray<UInt>::type_iterator type_end = el_list.lastType(spatial_dimension, _not_ghost, _ek_regular); /// loop over elements of the fragment for (; type_it != type_end; ++type_it) { ElementType type = *type_it; UInt nb_element = el_list(type).getSize(); nb_elements_per_fragment(*fragment_index_it) += nb_element; } } /// sum values over all processors StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); comm.allReduce(nb_elements_per_fragment.storage(), global_nb_fragment, _so_sum); if (dump_data) createDumpDataArray(nb_elements_per_fragment, "elements per fragment"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <typename T> void FragmentManager::createDumpDataArray(Array<T> & data, std::string name, bool fragment_index_output) { AKANTU_DEBUG_IN(); if (data.getSize() == 0) return; typedef typename Array<T>::vector_iterator data_iterator; Mesh & mesh_not_const = const_cast<Mesh &>(mesh); UInt spatial_dimension = mesh.getSpatialDimension(); UInt nb_component = data.getNbComponent(); UInt * fragment_index_it = fragment_index.storage(); data_iterator data_begin = data.begin(nb_component); /// loop over fragments for(const_element_group_iterator it(element_group_begin()); it != element_group_end(); ++it, ++fragment_index_it) { const ElementGroup & fragment = *(it->second); /// loop over cluster types ElementGroup::type_iterator type_it = fragment.firstType(spatial_dimension); ElementGroup::type_iterator type_end = fragment.lastType(spatial_dimension); for(; type_it != type_end; ++type_it) { ElementType type = *type_it; /// init mesh data Array<T> * mesh_data = mesh_not_const.getDataPointer<T>(name, type, _not_ghost, nb_component); data_iterator mesh_data_begin = mesh_data->begin(nb_component); ElementGroup::const_element_iterator el_it = fragment.element_begin(type); ElementGroup::const_element_iterator el_end = fragment.element_end(type); /// fill mesh data if (fragment_index_output) { for (; el_it != el_end; ++el_it) { Vector<T> md_tmp(mesh_data_begin[*el_it]); md_tmp(0) = *fragment_index_it; } } else { for (; el_it != el_end; ++el_it) { Vector<T> md_tmp(mesh_data_begin[*el_it]); md_tmp = data_begin[*fragment_index_it]; } } } } AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.hh index 2c04d8eb2..4cfed97eb 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.hh +++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.hh @@ -1,174 +1,174 @@ /** * @file fragment_manager.hh * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Thu Jan 23 2014 * @date last modification: Mon Dec 14 2015 * * @brief Group manager to handle fragments * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_FRAGMENT_MANAGER_HH__ #define __AKANTU_FRAGMENT_MANAGER_HH__ #include "group_manager.hh" #include "solid_mechanics_model_cohesive.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ class FragmentManager : public GroupManager { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FragmentManager(SolidMechanicsModelCohesive & model, bool dump_data = true, const ID & id = "fragment_manager", const MemoryID & memory_id = 0); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ private: /// store mass density per integration point void storeMassDensityPerIntegrationPoint(); /// integrate an elemental field multiplied by density on global /// fragments void integrateFieldOnFragments(ElementTypeMapArray<Real> & field, Array<Real> & output); /// compute fragments' mass void computeMass(); /// create dump data for a single array template <typename T> void createDumpDataArray(Array<T> & data, std::string name, bool fragment_index_output = false); public: /// build fragment list (cohesive elements are considered broken if /// damage >= damage_limit) void buildFragments(Real damage_limit = 1.); /// compute fragments' center of mass void computeCenterOfMass(); /// compute fragments' velocity void computeVelocity(); /// computes principal moments of inertia with respect to the center /// of mass of each fragment void computeInertiaMoments(); /// compute all fragments' data void computeAllData(); /// compute number of elements per fragment void computeNbElementsPerFragment(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get number of fragments AKANTU_GET_MACRO(NbFragment, global_nb_fragment, UInt); /// get fragments' mass AKANTU_GET_MACRO(Mass, mass, const Array<Real> &); /// get fragments' center of mass AKANTU_GET_MACRO(CenterOfMass, mass_center, const Array<Real> &); /// get fragments' velocity AKANTU_GET_MACRO(Velocity, velocity, const Array<Real> &); /// get fragments' principal moments of inertia AKANTU_GET_MACRO(MomentsOfInertia, inertia_moments, const Array<Real> &); /// get fragments' principal directions AKANTU_GET_MACRO(PrincipalDirections, principal_directions, const Array<Real> &); /// get number of elements per fragment AKANTU_GET_MACRO(NbElementsPerFragment, nb_elements_per_fragment, const Array<UInt> &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// local_fragment index Array<UInt> fragment_index; /// global number of fragments (parallel simulations) UInt global_nb_fragment; /// number of fragments UInt nb_fragment; /// cohesive solid mechanics model associated SolidMechanicsModelCohesive & model; /// fragments' center of mass Array<Real> mass_center; /// fragments' mass Array<Real> mass; /// fragments' velocity Array<Real> velocity; /// fragments' principal moments of inertia with respect to the /// center of mass Array<Real> inertia_moments; /// fragments' principal directions Array<Real> principal_directions; /// quadrature points' coordinates ElementTypeMapArray<Real> quad_coordinates; /// mass density per quadrature point ElementTypeMapArray<Real> mass_density; /// fragment filter Array<UInt> nb_elements_per_fragment; /// dump data bool dump_data; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_FRAGMENT_MANAGER_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc index 2cce818e8..2c8d683bb 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc @@ -1,97 +1,97 @@ /** * @file material_selector_cohesive.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Dec 11 2015 * @date last modification: Mon Dec 14 2015 * * @brief Material selector for cohesive elements * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_selector_cohesive.hh" #include "solid_mechanics_model_cohesive.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ DefaultMaterialCohesiveSelector::DefaultMaterialCohesiveSelector( const SolidMechanicsModelCohesive &model) : DefaultMaterialSelector(model.getMaterialByElement()), facet_material(model.getFacetMaterial()), mesh(model.getMesh()) {} /* -------------------------------------------------------------------------- */ UInt DefaultMaterialCohesiveSelector::operator()(const Element &element) { if (Mesh::getKind(element.type) == _ek_cohesive) { try { const Array<Element> &cohesive_el_to_facet = mesh.getMeshFacets().getSubelementToElement(element.type, element.ghost_type); bool third_dimension = (mesh.getSpatialDimension() == 3); const Element &facet = cohesive_el_to_facet(element.element, third_dimension); if (facet_material.exists(facet.type, facet.ghost_type)) { return facet_material(facet.type, facet.ghost_type)(facet.element); } else { return MaterialSelector::operator()(element); } } catch (...) { return MaterialSelector::operator()(element); } } else if (Mesh::getSpatialDimension(element.type) == mesh.getSpatialDimension() - 1) { return facet_material(element.type, element.ghost_type)(element.element); } else { return DefaultMaterialSelector::operator()(element); } } /* -------------------------------------------------------------------------- */ MeshDataMaterialCohesiveSelector::MeshDataMaterialCohesiveSelector( const SolidMechanicsModelCohesive &model) : MeshDataMaterialSelector<std::string>("physical_names", model), mesh_facets(model.getMeshFacets()), material_index(mesh_facets.getData<UInt>("physical_names")) { third_dimension = (model.getSpatialDimension() == 3); } /* -------------------------------------------------------------------------- */ UInt MeshDataMaterialCohesiveSelector::operator()(const Element &element) { if (element.kind == _ek_cohesive) { const Array<Element> &cohesive_el_to_facet = mesh_facets.getSubelementToElement(element.type, element.ghost_type); const Element &facet = cohesive_el_to_facet(element.element, third_dimension); UInt material_id = material_index(facet.type, facet.ghost_type)(facet.element); UInt fallback_id = MaterialSelector::operator()(element); return std::max(material_id,fallback_id); } else return MeshDataMaterialSelector<std::string>::operator()(element); } -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.hh index 8d423a4b9..c2f8b7501 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.hh +++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.hh @@ -1,76 +1,76 @@ /** * @file material_selector_cohesive.hh * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Dec 11 2015 * @date last modification: Mon Dec 14 2015 * * @brief Material selectors for cohesive elements * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_selector.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class SolidMechanicsModelCohesive; } -__BEGIN_AKANTU__ +namespace akantu { #ifndef __AKANTU_MATERIAL_SELECTOR_COHESIVE_HH__ #define __AKANTU_MATERIAL_SELECTOR_COHESIVE_HH__ /* -------------------------------------------------------------------------- */ /** * class that assigns the first cohesive material by default to the * cohesive elements */ class DefaultMaterialCohesiveSelector : public DefaultMaterialSelector { public: DefaultMaterialCohesiveSelector(const SolidMechanicsModelCohesive & model); virtual UInt operator()(const Element & element); private: const ElementTypeMapArray<UInt> & facet_material; const Mesh & mesh; }; /* -------------------------------------------------------------------------- */ /// To be used with intrinsic elements inserted along mesh physical surfaces class MeshDataMaterialCohesiveSelector : public MeshDataMaterialSelector<std::string> { public: MeshDataMaterialCohesiveSelector(const SolidMechanicsModelCohesive & model); virtual UInt operator()(const Element & element); protected: const Mesh &mesh_facets; const ElementTypeMapArray<UInt> & material_index; bool third_dimension; }; #endif /* __AKANTU_MATERIAL_SELECTOR_COHESIVE_HH__ */ -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc index 0156d06eb..c09dc035c 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc @@ -1,794 +1,794 @@ /** * @file solid_mechanics_model_cohesive.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue May 08 2012 * @date last modification: Wed Jan 13 2016 * * @brief Solid mechanics model for cohesive elements * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <algorithm> #include "shape_cohesive.hh" #include "solid_mechanics_model_cohesive.hh" #include "dumpable_inline_impl.hh" #include "material_cohesive.hh" #ifdef AKANTU_USE_IOHELPER #include "dumper_paraview.hh" #endif /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { const SolidMechanicsModelCohesiveOptions default_solid_mechanics_model_cohesive_options(_explicit_lumped_mass, false, false); /* -------------------------------------------------------------------------- */ SolidMechanicsModelCohesive::SolidMechanicsModelCohesive( Mesh & mesh, UInt dim, const ID & id, const MemoryID & memory_id) : SolidMechanicsModel(mesh, dim, id, memory_id), tangents("tangents", id), facet_stress("facet_stress", id), facet_material("facet_material", id) { AKANTU_DEBUG_IN(); inserter = NULL; #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) facet_synchronizer = NULL; facet_stress_synchronizer = NULL; cohesive_element_synchronizer = NULL; global_connectivity = NULL; #endif delete material_selector; material_selector = new DefaultMaterialCohesiveSelector(*this); this->registerEventHandler(*this); #if defined(AKANTU_USE_IOHELPER) this->mesh.registerDumper<DumperParaview>("cohesive elements", id); this->mesh.addDumpMeshToDumper("cohesive elements", mesh, spatial_dimension, _not_ghost, _ek_cohesive); #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SolidMechanicsModelCohesive::~SolidMechanicsModelCohesive() { AKANTU_DEBUG_IN(); delete inserter; #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) delete cohesive_element_synchronizer; delete facet_synchronizer; delete facet_stress_synchronizer; #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::setTimeStep(Real time_step) { SolidMechanicsModel::setTimeStep(time_step); #if defined(AKANTU_USE_IOHELPER) this->mesh.getDumper("cohesive elements").setTimeStep(time_step); #endif } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initFull(const ModelOptions & options) { AKANTU_DEBUG_IN(); const SolidMechanicsModelCohesiveOptions & smmc_options = dynamic_cast<const SolidMechanicsModelCohesiveOptions &>(options); this->is_extrinsic = smmc_options.extrinsic; if (!inserter) inserter = new CohesiveElementInserter(mesh, is_extrinsic, synch_parallel, id + ":cohesive_element_inserter"); SolidMechanicsModel::initFull(options); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initMaterials() { AKANTU_DEBUG_IN(); // make sure the material are instantiated if (!are_materials_instantiated) instantiateMaterials(); /// find the first cohesive material UInt cohesive_index = 0; while ( (dynamic_cast<MaterialCohesive *>(materials[cohesive_index]) == NULL) && cohesive_index <= materials.size()) ++cohesive_index; AKANTU_DEBUG_ASSERT(cohesive_index != materials.size(), "No cohesive materials in the material input file"); material_selector->setFallback(cohesive_index); // set the facet information in the material in case of dynamic insertion if (is_extrinsic) { const Mesh & mesh_facets = inserter->getMeshFacets(); mesh_facets.initElementTypeMapArray(facet_material, 1, spatial_dimension - 1); Element element; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { element.ghost_type = *gt; Mesh::type_iterator first = mesh_facets.firstType(spatial_dimension - 1, *gt); Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1, *gt); for (; first != last; ++first) { element.type = *first; Array<UInt> & f_material = facet_material(*first, *gt); UInt nb_element = mesh_facets.getNbElement(*first, *gt); f_material.resize(nb_element); f_material.set(cohesive_index); for (UInt el = 0; el < nb_element; ++el) { element.element = el; UInt mat_index = (*material_selector)(element); f_material(el) = mat_index; MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(*materials[mat_index]); mat.addFacet(element); } } } SolidMechanicsModel::initMaterials(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (facet_synchronizer != NULL) inserter->initParallel(facet_synchronizer, cohesive_element_synchronizer); // inserter->initParallel(facet_synchronizer, synch_parallel); #endif initAutomaticInsertion(); } else { // TODO think of something a bit mor consistant than just coding the first // thing that comes in Fabian's head.... typedef ParserSection::const_section_iterator const_section_iterator; std::pair<const_section_iterator, const_section_iterator> sub_sections = this->parser->getSubSections(_st_mesh); if (sub_sections.first != sub_sections.second) { std::string cohesive_surfaces = sub_sections.first->getParameter("cohesive_surfaces"); this->initIntrinsicCohesiveMaterials(cohesive_surfaces); } else { this->initIntrinsicCohesiveMaterials(cohesive_index); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initIntrinsicCohesiveMaterials( std::string cohesive_surfaces) { AKANTU_DEBUG_IN(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (facet_synchronizer != NULL) inserter->initParallel(facet_synchronizer, cohesive_element_synchronizer); // inserter->initParallel(facet_synchronizer, synch_parallel); #endif std::istringstream split(cohesive_surfaces); std::string physname; while (std::getline(split, physname, ',')) { AKANTU_DEBUG_INFO( "Pre-inserting cohesive elements along facets from physical surface: " << physname); insertElementsFromMeshData(physname); } synchronizeInsertionData(); SolidMechanicsModel::initMaterials(); if (is_default_material_selector) delete material_selector; material_selector = new MeshDataMaterialCohesiveSelector(*this); UInt nb_new_elements = inserter->insertElements(); if (nb_new_elements > 0) { this->reinitializeSolver(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::synchronizeInsertionData() { #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (facet_synchronizer != NULL) { facet_synchronizer->asynchronousSynchronize(*inserter, _gst_ce_groups); facet_synchronizer->waitEndSynchronize(*inserter, _gst_ce_groups); } #endif } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initIntrinsicCohesiveMaterials( UInt cohesive_index) { AKANTU_DEBUG_IN(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { Mesh::type_iterator first = mesh.firstType(spatial_dimension, *gt, _ek_cohesive); Mesh::type_iterator last = mesh.lastType(spatial_dimension, *gt, _ek_cohesive); for (; first != last; ++first) { Array<UInt> & mat_indexes = this->material_index(*first, *gt); Array<UInt> & mat_loc_num = this->material_local_numbering(*first, *gt); mat_indexes.set(cohesive_index); mat_loc_num.clear(); } } #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (facet_synchronizer != NULL) inserter->initParallel(facet_synchronizer, cohesive_element_synchronizer); // inserter->initParallel(facet_synchronizer, synch_parallel); #endif SolidMechanicsModel::initMaterials(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Initialize the model,basically it pre-compute the shapes, shapes derivatives * and jacobian * */ void SolidMechanicsModelCohesive::initModel() { AKANTU_DEBUG_IN(); SolidMechanicsModel::initModel(); registerFEEngineObject<MyFEEngineCohesiveType>("CohesiveFEEngine", mesh, spatial_dimension); /// add cohesive type connectivity ElementType type = _not_defined; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType type_ghost = *gt; Mesh::type_iterator it = mesh.firstType(spatial_dimension, type_ghost); Mesh::type_iterator last = mesh.lastType(spatial_dimension, type_ghost); for (; it != last; ++it) { const Array<UInt> & connectivity = mesh.getConnectivity(*it, type_ghost); if (connectivity.getSize() != 0) { type = *it; ElementType type_facet = Mesh::getFacetType(type); ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet); mesh.addConnectivityType(type_cohesive, type_ghost); } } } AKANTU_DEBUG_ASSERT(type != _not_defined, "No elements in the mesh"); getFEEngine("CohesiveFEEngine").initShapeFunctions(_not_ghost); getFEEngine("CohesiveFEEngine").initShapeFunctions(_ghost); registerFEEngineObject<MyFEEngineFacetType>("FacetsFEEngine", mesh.getMeshFacets(), spatial_dimension - 1); if (is_extrinsic) { getFEEngine("FacetsFEEngine").initShapeFunctions(_not_ghost); getFEEngine("FacetsFEEngine").initShapeFunctions(_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::limitInsertion(BC::Axis axis, Real first_limit, Real second_limit) { AKANTU_DEBUG_IN(); inserter->setLimit(axis, first_limit, second_limit); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::insertIntrinsicElements() { AKANTU_DEBUG_IN(); UInt nb_new_elements = inserter->insertIntrinsicElements(); if (nb_new_elements > 0) { this->reinitializeSolver(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::insertElementsFromMeshData( std::string physname) { AKANTU_DEBUG_IN(); UInt material_index = SolidMechanicsModel::getMaterialIndex(physname); inserter->insertIntrinsicElements(physname, material_index); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initAutomaticInsertion() { AKANTU_DEBUG_IN(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (facet_stress_synchronizer != NULL) { DataAccessor * data_accessor = this; const ElementTypeMapArray<UInt> & rank_to_element = synch_parallel->getPrankToElement(); facet_stress_synchronizer->updateFacetStressSynchronizer( *inserter, rank_to_element, *data_accessor); } #endif inserter->getMeshFacets().initElementTypeMapArray( facet_stress, 2 * spatial_dimension * spatial_dimension, spatial_dimension - 1); resizeFacetStress(); /// compute normals on facets computeNormals(); initStressInterpolation(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::updateAutomaticInsertion() { AKANTU_DEBUG_IN(); inserter->limitCheckFacets(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (facet_stress_synchronizer != NULL) { DataAccessor * data_accessor = this; const ElementTypeMapArray<UInt> & rank_to_element = synch_parallel->getPrankToElement(); facet_stress_synchronizer->updateFacetStressSynchronizer( *inserter, rank_to_element, *data_accessor); } #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initStressInterpolation() { Mesh & mesh_facets = inserter->getMeshFacets(); /// compute quadrature points coordinates on facets Array<Real> & position = mesh.getNodes(); ElementTypeMapArray<Real> quad_facets("quad_facets", id); mesh_facets.initElementTypeMapArray(quad_facets, spatial_dimension, spatial_dimension - 1); getFEEngine("FacetsFEEngine") .interpolateOnIntegrationPoints(position, quad_facets); /// compute elements quadrature point positions and build /// element-facet quadrature points data structure ElementTypeMapArray<Real> elements_quad_facets("elements_quad_facets", id); mesh.initElementTypeMapArray(elements_quad_facets, spatial_dimension, spatial_dimension); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType elem_gt = *gt; Mesh::type_iterator it = mesh.firstType(spatial_dimension, elem_gt); Mesh::type_iterator last = mesh.lastType(spatial_dimension, elem_gt); for (; it != last; ++it) { ElementType type = *it; UInt nb_element = mesh.getNbElement(type, elem_gt); if (nb_element == 0) continue; /// compute elements' quadrature points and list of facet /// quadrature points positions by element Array<Element> & facet_to_element = mesh_facets.getSubelementToElement(type, elem_gt); UInt nb_facet_per_elem = facet_to_element.getNbComponent(); Array<Real> & el_q_facet = elements_quad_facets(type, elem_gt); ElementType facet_type = Mesh::getFacetType(type); UInt nb_quad_per_facet = getFEEngine("FacetsFEEngine").getNbIntegrationPoints(facet_type); el_q_facet.resize(nb_element * nb_facet_per_elem * nb_quad_per_facet); for (UInt el = 0; el < nb_element; ++el) { for (UInt f = 0; f < nb_facet_per_elem; ++f) { Element global_facet_elem = facet_to_element(el, f); UInt global_facet = global_facet_elem.element; GhostType facet_gt = global_facet_elem.ghost_type; const Array<Real> & quad_f = quad_facets(facet_type, facet_gt); for (UInt q = 0; q < nb_quad_per_facet; ++q) { for (UInt s = 0; s < spatial_dimension; ++s) { el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet + f * nb_quad_per_facet + q, s) = quad_f(global_facet * nb_quad_per_facet + q, s); } } } } } } /// loop over non cohesive materials for (UInt m = 0; m < materials.size(); ++m) { try { MaterialCohesive & mat __attribute__((unused)) = dynamic_cast<MaterialCohesive &>(*materials[m]); } catch (std::bad_cast &) { /// initialize the interpolation function materials[m]->initElementalFieldInterpolation(elements_quad_facets); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::updateResidual(bool need_initialize) { AKANTU_DEBUG_IN(); if (need_initialize) initializeUpdateResidualData(); // f -= fint std::vector<Material *>::iterator mat_it; for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { try { MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(**mat_it); mat.computeTraction(_not_ghost); } catch (std::bad_cast & bce) { } } SolidMechanicsModel::updateResidual(false); if (isExplicit()) { for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { try { MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(**mat_it); mat.computeEnergies(); } catch (std::bad_cast & bce) { } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::computeNormals() { AKANTU_DEBUG_IN(); Mesh & mesh_facets = this->inserter->getMeshFacets(); this->getFEEngine("FacetsFEEngine") .computeNormalsOnIntegrationPoints(_not_ghost); /** * @todo store tangents while computing normals instead of * recomputing them as follows: */ /* ------------------------------------------------------------------------ */ UInt tangent_components = spatial_dimension * (spatial_dimension - 1); mesh_facets.initElementTypeMapArray(tangents, tangent_components, spatial_dimension - 1); Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1); Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1); for (; it != last; ++it) { ElementType facet_type = *it; const Array<Real> & normals = this->getFEEngine("FacetsFEEngine") .getNormalsOnIntegrationPoints(facet_type); Array<Real> & tangents = this->tangents(facet_type); Math::compute_tangents(normals, tangents); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::interpolateStress() { ElementTypeMapArray<Real> by_elem_result("temporary_stress_by_facets", id); for (UInt m = 0; m < materials.size(); ++m) { try { MaterialCohesive & mat __attribute__((unused)) = dynamic_cast<MaterialCohesive &>(*materials[m]); } catch (std::bad_cast &) { /// interpolate stress on facet quadrature points positions materials[m]->interpolateStressOnFacets(facet_stress, by_elem_result); } } #if defined(AKANTU_DEBUG_TOOLS) debug::element_manager.printData( debug::_dm_model_cohesive, "Interpolated stresses before", facet_stress); #endif synch_registry->synchronize(_gst_smmc_facets_stress); #if defined(AKANTU_DEBUG_TOOLS) debug::element_manager.printData(debug::_dm_model_cohesive, "Interpolated stresses", facet_stress); #endif } /* -------------------------------------------------------------------------- */ UInt SolidMechanicsModelCohesive::checkCohesiveStress() { interpolateStress(); for (UInt m = 0; m < materials.size(); ++m) { try { MaterialCohesive & mat_cohesive = dynamic_cast<MaterialCohesive &>(*materials[m]); /// check which not ghost cohesive elements are to be created mat_cohesive.checkInsertion(); } catch (std::bad_cast &) { } } /* if(static and extrinsic) { check max mean stresses and change inserter.getInsertionFacets(type_facet); } */ /// communicate data among processors synch_registry->synchronize(_gst_smmc_facets); /// insert cohesive elements UInt nb_new_elements = inserter->insertElements(); if (nb_new_elements > 0) { this->reinitializeSolver(); } return nb_new_elements; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::onElementsAdded( const Array<Element> & element_list, const NewElementsEvent & event) { AKANTU_DEBUG_IN(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) updateCohesiveSynchronizers(); #endif SolidMechanicsModel::onElementsAdded(element_list, event); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (cohesive_element_synchronizer != NULL) cohesive_element_synchronizer->computeAllBufferSizes(*this); #endif /// update shape functions getFEEngine("CohesiveFEEngine").initShapeFunctions(_not_ghost); getFEEngine("CohesiveFEEngine").initShapeFunctions(_ghost); if (is_extrinsic) resizeFacetStress(); /// if (method != _explicit_lumped_mass) { /// this->initSolver(); /// } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::onNodesAdded( const Array<UInt> & doubled_nodes, __attribute__((unused)) const NewNodesEvent & event) { AKANTU_DEBUG_IN(); UInt nb_new_nodes = doubled_nodes.getSize(); Array<UInt> nodes_list(nb_new_nodes); for (UInt n = 0; n < nb_new_nodes; ++n) nodes_list(n) = doubled_nodes(n, 1); SolidMechanicsModel::onNodesAdded(nodes_list, event); for (UInt n = 0; n < nb_new_nodes; ++n) { UInt old_node = doubled_nodes(n, 0); UInt new_node = doubled_nodes(n, 1); for (UInt dim = 0; dim < spatial_dimension; ++dim) { (*displacement)(new_node, dim) = (*displacement)(old_node, dim); (*velocity)(new_node, dim) = (*velocity)(old_node, dim); (*acceleration)(new_node, dim) = (*acceleration)(old_node, dim); (*blocked_dofs)(new_node, dim) = (*blocked_dofs)(old_node, dim); if (current_position) (*current_position)(new_node, dim) = (*current_position)(old_node, dim); if (increment_acceleration) (*increment_acceleration)(new_node, dim) = (*increment_acceleration)(old_node, dim); if (increment) (*increment)(new_node, dim) = (*increment)(old_node, dim); if (previous_displacement) (*previous_displacement)(new_node, dim) = (*previous_displacement)(old_node, dim); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::onEndSolveStep( __attribute__((unused)) const AnalysisMethod & method) { AKANTU_DEBUG_IN(); /* * This is required because the Cauchy stress is the stress measure that * is used to check the insertion of cohesive elements */ std::vector<Material *>::iterator mat_it; for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; if (mat.isFiniteDeformation()) mat.computeAllCauchyStresses(_not_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "SolidMechanicsModelCohesive [" << std::endl; SolidMechanicsModel::printself(stream, indent + 1); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::resizeFacetStress() { AKANTU_DEBUG_IN(); Mesh & mesh_facets = inserter->getMeshFacets(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, ghost_type); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, ghost_type); for (; it != end; ++it) { ElementType type = *it; UInt nb_facet = mesh_facets.getNbElement(type, ghost_type); UInt nb_quadrature_points = getFEEngine("FacetsFEEngine") .getNbIntegrationPoints(type, ghost_type); UInt new_size = nb_facet * nb_quadrature_points; facet_stress(type, ghost_type).resize(new_size); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::addDumpGroupFieldToDumper( const std::string & dumper_name, const std::string & field_id, const std::string & group_name, const ElementKind & element_kind, bool padding_flag) { AKANTU_DEBUG_IN(); UInt spatial_dimension = this->spatial_dimension; ElementKind _element_kind = element_kind; if (dumper_name == "cohesive elements") { _element_kind = _ek_cohesive; } else if (dumper_name == "facets") { spatial_dimension = this->spatial_dimension - 1; } SolidMechanicsModel::addDumpGroupFieldToDumper(dumper_name, field_id, group_name, spatial_dimension, _element_kind, padding_flag); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::onDump() { this->flattenAllRegisteredInternals(_ek_cohesive); SolidMechanicsModel::onDump(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh index 5026ad0db..75ef8a48c 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh +++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh @@ -1,287 +1,287 @@ /** * @file solid_mechanics_model_cohesive.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue May 08 2012 * @date last modification: Mon Dec 14 2015 * * @brief Solid mechanics model for cohesive elements * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__ #define __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__ #include "cohesive_element_inserter.hh" #include "material_selector_cohesive.hh" #include "solid_mechanics_model.hh" #include "solid_mechanics_model_event_handler.hh" #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) #include "facet_stress_synchronizer.hh" #include "facet_synchronizer.hh" #endif /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ struct FacetsCohesiveIntegrationOrderFunctor { template <ElementType type, ElementType cohesive_type = CohesiveFacetProperty<type>::cohesive_type> struct _helper { static constexpr int get() { return ElementClassProperty<cohesive_type>::polynomial_degree; } }; template <ElementType type> struct _helper<type, _not_defined> { static constexpr int get() { return ElementClassProperty<type>::polynomial_degree; } }; template <ElementType type> static inline constexpr int getOrder() { return _helper<type>::get(); } }; /* -------------------------------------------------------------------------- */ struct SolidMechanicsModelCohesiveOptions : public SolidMechanicsModelOptions { SolidMechanicsModelCohesiveOptions( AnalysisMethod analysis_method = _explicit_lumped_mass, bool extrinsic = false, bool no_init_materials = false) : SolidMechanicsModelOptions(analysis_method, no_init_materials), extrinsic(extrinsic) {} bool extrinsic; }; extern const SolidMechanicsModelCohesiveOptions default_solid_mechanics_model_cohesive_options; /* -------------------------------------------------------------------------- */ /* Solid Mechanics Model for Cohesive elements */ /* -------------------------------------------------------------------------- */ class SolidMechanicsModelCohesive : public SolidMechanicsModel, public SolidMechanicsModelEventHandler { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: class NewCohesiveNodesEvent : public NewNodesEvent { public: AKANTU_GET_MACRO_NOT_CONST(OldNodesList, old_nodes, Array<UInt> &); AKANTU_GET_MACRO(OldNodesList, old_nodes, const Array<UInt> &); protected: Array<UInt> old_nodes; }; typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive> MyFEEngineCohesiveType; typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular, FacetsCohesiveIntegrationOrderFunctor> MyFEEngineFacetType; SolidMechanicsModelCohesive(Mesh & mesh, UInt spatial_dimension = _all_dimensions, const ID & id = "solid_mechanics_model_cohesive", const MemoryID & memory_id = 0); virtual ~SolidMechanicsModelCohesive(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// set the value of the time step void setTimeStep(Real time_step); /// assemble the residual for the explicit scheme virtual void updateResidual(bool need_initialize = true); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /// function to perform a stress check on each facet and insert /// cohesive elements if needed (returns the number of new cohesive /// elements) UInt checkCohesiveStress(); /// interpolate stress on facets void interpolateStress(); /// initialize the cohesive model void initFull(const ModelOptions & options = default_solid_mechanics_model_cohesive_options); /// initialize the model void initModel(); /// initialize cohesive material void initMaterials(); /// init facet filters for cohesive materials void initFacetFilter(); /// limit the cohesive element insertion to a given area void limitInsertion(BC::Axis axis, Real first_limit, Real second_limit); /// update automatic insertion after a change in the element inserter void updateAutomaticInsertion(); /// insert intrinsic cohesive elements void insertIntrinsicElements(); // synchronize facets physical data before insertion along physical surfaces void synchronizeInsertionData(); // template <SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria> // bool solveStepCohesive(Real tolerance, Real & error, UInt max_iteration = 100, // bool load_reduction = false, // Real tol_increase_factor = 1.0, // bool do_not_factorize = false); /// initialize stress interpolation void initStressInterpolation(); private: /// initialize cohesive material with intrinsic insertion (by default) void initIntrinsicCohesiveMaterials(UInt cohesive_index); /// initialize cohesive material with intrinsic insertion (if physical /// surfaces are precised) void initIntrinsicCohesiveMaterials(std::string cohesive_surfaces); /// insert cohesive elements along a given physical surface of the mesh void insertElementsFromMeshData(std::string physical_name); /// initialize completely the model for extrinsic elements void initAutomaticInsertion(); /// compute facets' normals void computeNormals(); /// resize facet stress void resizeFacetStress(); /// init facets_check array void initFacetsCheck(); /* ------------------------------------------------------------------------ */ /* Mesh Event Handler inherited members */ /* ------------------------------------------------------------------------ */ protected: virtual void onNodesAdded(const Array<UInt> & nodes_list, const NewNodesEvent & event); virtual void onElementsAdded(const Array<Element> & nodes_list, const NewElementsEvent & event); /* ------------------------------------------------------------------------ */ /* SolidMechanicsModelEventHandler inherited members */ /* ------------------------------------------------------------------------ */ public: virtual void onEndSolveStep(const AnalysisMethod & method); /* ------------------------------------------------------------------------ */ /* Dumpable interface */ /* ------------------------------------------------------------------------ */ public: virtual void onDump(); virtual void addDumpGroupFieldToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name, const ElementKind & element_kind, bool padding_flag); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get facet mesh AKANTU_GET_MACRO(MeshFacets, mesh.getMeshFacets(), const Mesh &); /// get stress on facets vector AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(StressOnFacets, facet_stress, Real); /// get facet material AKANTU_GET_MACRO_BY_ELEMENT_TYPE(FacetMaterial, facet_material, UInt); /// get facet material AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(FacetMaterial, facet_material, UInt); /// get facet material AKANTU_GET_MACRO(FacetMaterial, facet_material, const ElementTypeMapArray<UInt> &); /// @todo THIS HAS TO BE CHANGED AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Tangents, tangents, Real); /// get element inserter AKANTU_GET_MACRO_NOT_CONST(ElementInserter, *inserter, CohesiveElementInserter &); /// get is_extrinsic boolean AKANTU_GET_MACRO(IsExtrinsic, is_extrinsic, bool); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// @todo store tangents when normals are computed: ElementTypeMapArray<Real> tangents; /// stress on facets on the two sides by quadrature point ElementTypeMapArray<Real> facet_stress; /// material to use if a cohesive element is created on a facet ElementTypeMapArray<UInt> facet_material; bool is_extrinsic; /// cohesive element inserter CohesiveElementInserter * inserter; #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) #include "solid_mechanics_model_cohesive_parallel.hh" #endif }; /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const SolidMechanicsModelCohesive & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #include "solid_mechanics_model_cohesive_inline_impl.cc" #endif /* __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.cc index c9fbee16c..d196dd633 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.cc @@ -1,310 +1,310 @@ /** * @file solid_mechanics_model_cohesive_inline_impl.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jan 18 2013 * @date last modification: Thu Jan 14 2016 * * @brief Implementation of inline functions for the Cohesive element model * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include <algorithm> #include "material_cohesive.hh" #ifndef __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_INLINE_IMPL_CC__ #define __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_INLINE_IMPL_CC__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria> bool SolidMechanicsModelCohesive::solveStepCohesive(Real tolerance, Real & error, UInt max_iteration, bool load_reduction, Real tol_increase_factor, bool do_not_factorize) { EventManager::sendEvent(SolidMechanicsModelEvent::BeforeSolveStepEvent(method)); this->implicitPred(); bool insertion_new_element = true; bool converged = false; Array<Real> * displacement_tmp = NULL; Array<Real> * velocity_tmp = NULL; Array<Real> * acceleration_tmp = NULL; StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int prank = comm.whoAmI(); /// Loop for the insertion of new cohesive elements while (insertion_new_element) { if (is_extrinsic) { /** * If in extrinsic the solution of the previous incremental step * is saved in temporary arrays created for displacements, * velocities and accelerations. Such arrays are used to find * the solution with the Newton-Raphson scheme (this is done by * pointing the pointer "displacement" to displacement_tmp). In * this way, inside the array "displacement" is kept the * solution of the previous incremental step, and in * "displacement_tmp" is saved the current solution. */ Array<Real> * tmp_swap; if(!displacement_tmp) { displacement_tmp = new Array<Real>(*(this->displacement)); } else { displacement_tmp->resize(this->displacement->getSize()); displacement_tmp->copy(*(this->displacement)); } tmp_swap = displacement_tmp; displacement_tmp = this->displacement; this->displacement = tmp_swap; if(!velocity_tmp) { velocity_tmp = new Array<Real>(*(this->velocity)); } else { velocity_tmp->resize(this->velocity->getSize()); velocity_tmp->copy(*(this->velocity)); } tmp_swap = velocity_tmp; velocity_tmp = this->velocity; this->velocity = tmp_swap; if(!acceleration_tmp) { acceleration_tmp = new Array<Real>(*(this->acceleration)); } else { acceleration_tmp->resize(this->acceleration->getSize()); acceleration_tmp->copy(*(this->acceleration)); } tmp_swap = acceleration_tmp; acceleration_tmp = this->acceleration; this->acceleration = tmp_swap; } this->updateResidual(); AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL, "You should first initialize the implicit solver and assemble the stiffness matrix"); bool need_factorize = !do_not_factorize; if (method ==_implicit_dynamic) { AKANTU_DEBUG_ASSERT(mass_matrix != NULL, "You should first initialize the implicit solver and assemble the mass matrix"); } switch (cmethod) { case _scm_newton_raphson_tangent: case _scm_newton_raphson_tangent_not_computed: break; case _scm_newton_raphson_tangent_modified: this->assembleStiffnessMatrix(); break; default: AKANTU_DEBUG_ERROR("The resolution method " << cmethod << " has not been implemented!"); } UInt iter = 0; converged = false; error = 0.; if(criteria == _scc_residual) { converged = this->testConvergence<criteria> (tolerance, error); if(converged) return converged; } /// Loop to solve the nonlinear system do { if (cmethod == _scm_newton_raphson_tangent) this->assembleStiffnessMatrix(); solve<NewmarkBeta::_displacement_corrector> (*increment, 1., need_factorize); this->implicitCorr(); this->updateResidual(); converged = this->testConvergence<criteria> (tolerance, error); iter++; AKANTU_DEBUG_INFO("[" << criteria << "] Convergence iteration " << std::setw(std::log10(max_iteration)) << iter << ": error " << error << (converged ? " < " : " > ") << tolerance); switch (cmethod) { case _scm_newton_raphson_tangent: need_factorize = true; break; case _scm_newton_raphson_tangent_not_computed: case _scm_newton_raphson_tangent_modified: need_factorize = false; break; default: AKANTU_DEBUG_ERROR("The resolution method " << cmethod << " has not been implemented!"); } } while (!converged && iter < max_iteration); /** * This is to save the obtained result and proceed with the * simulation even if the error is higher than the pre-fixed * tolerance. This is done only after loading reduction * (load_reduction = true). */ // if (load_reduction && (error < tolerance * tol_increase_factor)) converged = true; if ((error < tolerance * tol_increase_factor)) converged = true; if (converged) { } else if(iter == max_iteration) { if (prank==0){ AKANTU_DEBUG_WARNING("[" << criteria << "] Convergence not reached after " << std::setw(std::log10(max_iteration)) << iter << " iteration" << (iter == 1 ? "" : "s") << "!" << std::endl); } } if (is_extrinsic) { /** * If is extrinsic the pointer "displacement" is moved back to * the array displacement. In this way, the array displacement is * correctly resized during the checkCohesiveStress function (in * case new cohesive elements are added). This is possible * because the procedure called by checkCohesiveStress does not * use the displacement field (the correct one is now stored in * displacement_tmp), but directly the stress field that is * already computed. */ Array<Real> * tmp_swap; tmp_swap = displacement_tmp; displacement_tmp = this->displacement; this->displacement = tmp_swap; tmp_swap = velocity_tmp; velocity_tmp = this->velocity; this->velocity = tmp_swap; tmp_swap = acceleration_tmp; acceleration_tmp = this->acceleration; this->acceleration = tmp_swap; /// If convergence is reached, call checkCohesiveStress in order /// to check if cohesive elements have to be introduced if (converged){ UInt new_cohesive_elements = checkCohesiveStress(); if(new_cohesive_elements == 0){ insertion_new_element = false; } else { insertion_new_element = true; } } } if (!converged && load_reduction) insertion_new_element = false; /** * If convergence is not reached, there is the possibility to * return back to the main file and reduce the load. Before doing * this, a pre-fixed value as to be defined for the parameter * delta_max of the cohesive elements introduced in the current * incremental step. This is done by calling the function * checkDeltaMax. */ if (!converged) { insertion_new_element = false; for (UInt m = 0; m < materials.size(); ++m) { try { MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(*materials[m]); mat.checkDeltaMax(_not_ghost); } catch(std::bad_cast&) { } } } } //end loop for the insertion of new cohesive elements /** * When the solution to the current incremental step is computed (no * more cohesive elements have to be introduced), call the function * to compute the energies. */ if ((is_extrinsic && converged)) { for(UInt m = 0; m < materials.size(); ++m) { try { MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(*materials[m]); mat.computeEnergies(); } catch (std::bad_cast & bce) { } } EventManager::sendEvent(SolidMechanicsModelEvent::AfterSolveStepEvent(method)); /** * The function resetVariables is necessary to correctly set a * variable that permit to decrease locally the penalty parameter * for compression. */ for (UInt m = 0; m < materials.size(); ++m) { try { MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(*materials[m]); mat.resetVariables(_not_ghost); } catch(std::bad_cast&) { } } /// The correct solution is saved this->displacement->copy(*displacement_tmp); this->velocity ->copy(*velocity_tmp); this->acceleration->copy(*acceleration_tmp); } delete displacement_tmp; delete velocity_tmp; delete acceleration_tmp; return insertion_new_element; } -__END_AKANTU__ +} // akantu #if defined (AKANTU_PARALLEL_COHESIVE_ELEMENT) # include "solid_mechanics_model_cohesive_parallel_inline_impl.cc" #endif #endif /* __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_INLINE_IMPL_CC__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc index be8123014..caed2dda1 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc @@ -1,160 +1,160 @@ /** * @file embedded_interface_intersector.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Fri May 01 2015 * @date last modification: Mon Jan 04 2016 * * @brief Class that loads the interface from mesh and computes intersections * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "embedded_interface_intersector.hh" #include "mesh_segment_intersector.hh" /// Helper macro for types in the mesh. Creates an intersector and computes intersection queries #define INTERFACE_INTERSECTOR_CASE(dim, type) do { \ MeshSegmentIntersector<dim, type> intersector(this->mesh, interface_mesh); \ name_to_primitives_it = name_to_primitives_map.begin(); \ for (; name_to_primitives_it != name_to_primitives_end ; ++name_to_primitives_it) { \ intersector.setPhysicalName(name_to_primitives_it->first); \ intersector.buildResultFromQueryList(name_to_primitives_it->second); \ } } while(0) #define INTERFACE_INTERSECTOR_CASE_2D(type) INTERFACE_INTERSECTOR_CASE(2, type) #define INTERFACE_INTERSECTOR_CASE_3D(type) INTERFACE_INTERSECTOR_CASE(3, type) -__BEGIN_AKANTU__ +namespace akantu { EmbeddedInterfaceIntersector::EmbeddedInterfaceIntersector(Mesh & mesh, const Mesh & primitive_mesh) : MeshGeomAbstract(mesh), interface_mesh(mesh.getSpatialDimension(), "interface_mesh"), primitive_mesh(primitive_mesh) { // Initiating mesh connectivity and data interface_mesh.addConnectivityType(_segment_2, _not_ghost); interface_mesh.addConnectivityType(_segment_2, _ghost); interface_mesh.registerData<Element>("associated_element").alloc(0, 1, _segment_2); interface_mesh.registerData<std::string>("physical_names").alloc(0, 1, _segment_2); } EmbeddedInterfaceIntersector::~EmbeddedInterfaceIntersector() {} void EmbeddedInterfaceIntersector::constructData(GhostType ghost_type) { AKANTU_DEBUG_IN(); const UInt dim = this->mesh.getSpatialDimension(); if (dim == 1) AKANTU_DEBUG_ERROR("No embedded model in 1D. Deactivate intersection initialization"); Array<std::string> * physical_names = NULL; try { physical_names = &const_cast<Array<std::string> &>(this->primitive_mesh.getData<std::string>("physical_names", _segment_2)); } catch (debug::Exception & e) { AKANTU_DEBUG_ERROR("You must define physical names to reinforcements in order to use the embedded model"); throw e; } const UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(_segment_2); Array<UInt>::const_vector_iterator connectivity = primitive_mesh.getConnectivity(_segment_2).begin(nb_nodes_per_element); Array<std::string>::scalar_iterator names_it = physical_names->begin(), names_end = physical_names->end(); std::map<std::string, std::list<K::Segment_3> > name_to_primitives_map; // Loop over the physical names and register segment lists in name_to_primitives_map for (; names_it != names_end ; ++names_it) { UInt element_id = names_it - physical_names->begin(); const Vector<UInt> el_connectivity = connectivity[element_id]; K::Segment_3 segment = this->createSegment(el_connectivity); name_to_primitives_map[*names_it].push_back(segment); } // Loop over the background types of the mesh Mesh::type_iterator type_it = this->mesh.firstType(dim, _not_ghost), type_end = this->mesh.lastType(dim, _not_ghost); std::map<std::string, std::list<K::Segment_3> >::iterator name_to_primitives_it, name_to_primitives_end = name_to_primitives_map.end(); for (; type_it != type_end ; ++type_it) { // Used in AKANTU_BOOST_ELEMENT_SWITCH ElementType type = *type_it; AKANTU_DEBUG_INFO("Computing intersections with background element type " << type); switch(dim) { case 1: break; case 2: // Compute intersections for supported 2D elements AKANTU_BOOST_ELEMENT_SWITCH(INTERFACE_INTERSECTOR_CASE_2D, (_triangle_3) (_triangle_6)); break; case 3: // Compute intersections for supported 3D elements AKANTU_BOOST_ELEMENT_SWITCH(INTERFACE_INTERSECTOR_CASE_3D, (_tetrahedron_4)); break; } } AKANTU_DEBUG_OUT(); } K::Segment_3 EmbeddedInterfaceIntersector::createSegment(const Vector<UInt> & connectivity) { AKANTU_DEBUG_IN(); K::Point_3 * source = NULL, * target = NULL; const Array<Real> & nodes = this->primitive_mesh.getNodes(); if (this->mesh.getSpatialDimension() == 2) { source = new K::Point_3(nodes(connectivity(0), 0), nodes(connectivity(0), 1), 0.); target = new K::Point_3(nodes(connectivity(1), 0), nodes(connectivity(1), 1), 0.); } else if (this->mesh.getSpatialDimension() == 3) { source = new K::Point_3(nodes(connectivity(0), 0), nodes(connectivity(0), 1), nodes(connectivity(0), 2)); target = new K::Point_3(nodes(connectivity(1), 0), nodes(connectivity(1), 1), nodes(connectivity(1), 2)); } K::Segment_3 segment(*source, *target); delete source; delete target; AKANTU_DEBUG_OUT(); return segment; } -__END_AKANTU__ +} // akantu #undef INTERFACE_INTERSECTOR_CASE #undef INTERFACE_INTERSECTOR_CASE_2D #undef INTERFACE_INTERSECTOR_CASE_3D diff --git a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.hh b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.hh index d36d382d3..889a63c4e 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.hh +++ b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.hh @@ -1,91 +1,91 @@ /** * @file embedded_interface_intersector.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Fri May 01 2015 * @date last modification: Mon Dec 14 2015 * * @brief Class that loads the interface from mesh and computes intersections * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_EMBEDDED_INTERFACE_INTERSECTOR_HH__ #define __AKANTU_EMBEDDED_INTERFACE_INTERSECTOR_HH__ #include "aka_common.hh" #include "mesh_geom_common.hh" #include "mesh_geom_abstract.hh" #include "mesh_segment_intersector.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { typedef Cartesian K; /** * @brief Computes the intersections of the reinforcements defined in the primitive mesh * * The purpose of this class is to look for reinforcements in the primitive mesh, which * should be defined by physical groups with the same names as the reinforcement materials * in the model. * * It then constructs the CGAL primitives from the elements of those reinforcements * and computes the intersections with the background mesh, to create an `interface_mesh`, * which is in turn used by the EmbeddedInterfaceModel. * * @see MeshSegmentIntersector, MeshGeomAbstract * @see EmbeddedInterfaceModel */ class EmbeddedInterfaceIntersector : public MeshGeomAbstract { public: /// Construct from mesh and a reinforcement mesh explicit EmbeddedInterfaceIntersector(Mesh & mesh, const Mesh & primitive_mesh); /// Destructor virtual ~EmbeddedInterfaceIntersector(); public: /// Generate the interface mesh virtual void constructData(GhostType ghost_type = _not_ghost); /// Create a segment with an element connectivity K::Segment_3 createSegment(const Vector<UInt> & connectivity); /// Getter for interface mesh AKANTU_GET_MACRO_NOT_CONST(InterfaceMesh, interface_mesh, Mesh &); protected: /// Resulting mesh of intersection Mesh interface_mesh; /// Mesh used for primitive construction const Mesh & primitive_mesh; }; -__END_AKANTU__ +} // akantu #endif // __AKANTU_EMBEDDED_INTERFACE_INTERSECTOR_HH__ diff --git a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.cc b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.cc index 30d1db3f3..910af71ff 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.cc @@ -1,210 +1,210 @@ /** * @file embedded_interface_model.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Fri Mar 13 2015 * @date last modification: Mon Dec 14 2015 * * @brief Model of Solid Mechanics with embedded interfaces * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "embedded_interface_model.hh" #include "material_reinforcement.hh" #ifdef AKANTU_USE_IOHELPER # include "dumper_paraview.hh" # include "dumpable_inline_impl.hh" #endif /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { const EmbeddedInterfaceModelOptions default_embedded_interface_model_options(_explicit_lumped_mass, false, false); /* -------------------------------------------------------------------------- */ EmbeddedInterfaceModel::EmbeddedInterfaceModel(Mesh & mesh, Mesh & primitive_mesh, UInt spatial_dimension, const ID & id, const MemoryID & memory_id) : SolidMechanicsModel(mesh, spatial_dimension, id, memory_id), intersector(mesh, primitive_mesh), interface_mesh(NULL), primitive_mesh(primitive_mesh), interface_material_selector(NULL) { // This pointer should be deleted by ~SolidMechanicsModel() MaterialSelector * mat_sel_pointer = new MeshDataMaterialSelector<std::string>("physical_names", *this); this->setMaterialSelector(*mat_sel_pointer); interface_mesh = &(intersector.getInterfaceMesh()); // Create 1D FEEngine on the interface mesh registerFEEngineObject<MyFEEngineType>("EmbeddedInterfaceFEEngine", *interface_mesh, 1); } /* -------------------------------------------------------------------------- */ EmbeddedInterfaceModel::~EmbeddedInterfaceModel() { delete interface_material_selector; } /* -------------------------------------------------------------------------- */ void EmbeddedInterfaceModel::initFull(const ModelOptions & options) { const EmbeddedInterfaceModelOptions & eim_options = dynamic_cast<const EmbeddedInterfaceModelOptions &>(options); // We don't want to initiate materials before shape functions are initialized SolidMechanicsModelOptions dummy_options(eim_options.analysis_method, true); // Do no initialize interface_mesh if told so if (!eim_options.no_init_intersections) intersector.constructData(); // Initialize interface FEEngine FEEngine & engine = getFEEngine("EmbeddedInterfaceFEEngine"); engine.initShapeFunctions(_not_ghost); engine.initShapeFunctions(_ghost); SolidMechanicsModel::initFull(dummy_options); // This will call SolidMechanicsModel::initMaterials() last this->initMaterials(); #if defined(AKANTU_USE_IOHELPER) this->mesh.registerDumper<DumperParaview>("reinforcement", id); this->mesh.addDumpMeshToDumper("reinforcement", *interface_mesh, 1, _not_ghost, _ek_regular); #endif } /* -------------------------------------------------------------------------- */ // This function is very similar to SolidMechanicsModel's void EmbeddedInterfaceModel::initMaterials() { Element element; delete interface_material_selector; interface_material_selector = new InterfaceMeshDataMaterialSelector<std::string>("physical_names", *this); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { element.ghost_type = *gt; Mesh::type_iterator it = interface_mesh->firstType(1, *gt); Mesh::type_iterator end = interface_mesh->lastType(1, *gt); for (; it != end ; ++it) { UInt nb_element = interface_mesh->getNbElement(*it, *gt); element.type = *it; Array<UInt> & mat_indexes = material_index.alloc(nb_element, 1, *it, *gt); for (UInt el = 0 ; el < nb_element ; el++) { element.element = el; UInt mat_index = (*interface_material_selector)(element); AKANTU_DEBUG_ASSERT(mat_index < materials.size(), "The material selector returned an index that does not exist"); mat_indexes(element.element) = mat_index; materials.at(mat_index)->addElement(*it, el, *gt); } } } SolidMechanicsModel::initMaterials(); } // /** // * DO NOT REMOVE - This prevents the material reinforcement to register // * their number of components. Problems arise with AvgHomogenizingFunctor // * if the material reinforcement gives its number of components for a // * field. Since AvgHomogenizingFunctor verifies that all the fields // * have the same number of components, an exception is raised. // */ // ElementTypeMap<UInt> EmbeddedInterfaceModel::getInternalDataPerElem(const std::string & field_name, // const ElementKind & kind) { // if (!(this->isInternal(field_name,kind))) AKANTU_EXCEPTION("unknown internal " << field_name); // for (UInt m = 0; m < materials.size() ; ++m) { // if (materials[m]->isInternal<Real>(field_name, kind)) { // Material * mat = NULL; // switch(this->spatial_dimension) { // case 1: // mat = dynamic_cast<MaterialReinforcement<1> *>(materials[m]); // break; // case 2: // mat = dynamic_cast<MaterialReinforcement<2> *>(materials[m]); // break; // case 3: // mat = dynamic_cast<MaterialReinforcement<3> *>(materials[m]); // break; // } // if (mat == NULL && field_name != "stress_embedded") // return materials[m]->getInternalDataPerElem<Real>(field_name,kind); // else if (mat != NULL && field_name == "stress_embedded") // return mat->getInternalDataPerElem<Real>(field_name, kind, "EmbeddedInterfaceFEEngine"); // } // } // return ElementTypeMap<UInt>(); // } /* -------------------------------------------------------------------------- */ void EmbeddedInterfaceModel::addDumpGroupFieldToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name, const ElementKind & element_kind, bool padding_flag) { #ifdef AKANTU_USE_IOHELPER dumper::Field * field = NULL; // If dumper is reinforcement, create a 1D elemental field if (dumper_name == "reinforcement") field = this->createElementalField(field_id, group_name, padding_flag, 1, element_kind); else { try { SolidMechanicsModel::addDumpGroupFieldToDumper(dumper_name, field_id, group_name, element_kind, padding_flag); } catch (...) {} } if (field) { DumperIOHelper & dumper = mesh.getGroupDumper(dumper_name,group_name); Model::addDumpGroupFieldToDumper(field_id,field,dumper); } #endif } -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.hh b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.hh index 3960c2cf8..39edb360d 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.hh +++ b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.hh @@ -1,167 +1,167 @@ /** * @file embedded_interface_model.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Mon Dec 14 2015 * * @brief Model of Solid Mechanics with embedded interfaces * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_EMBEDDED_INTERFACE_MODEL_HH__ #define __AKANTU_EMBEDDED_INTERFACE_MODEL_HH__ #include "aka_common.hh" #include "solid_mechanics_model.hh" #include "mesh.hh" #include "embedded_interface_intersector.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /// Options for the EmbeddedInterfaceModel struct EmbeddedInterfaceModelOptions : SolidMechanicsModelOptions { /** * @brief Constructor for EmbeddedInterfaceModelOptions * @param analysis_method see SolidMeechanicsModelOptions * @param no_init_intersections ignores the embedded elements * @param no_init_materials see SolidMeechanicsModelOptions */ EmbeddedInterfaceModelOptions(AnalysisMethod analysis_method = _explicit_lumped_mass, bool no_init_intersections = false, bool no_init_materials = false): SolidMechanicsModelOptions(analysis_method, no_init_materials), no_init_intersections(no_init_intersections) {} /// Ignore the reinforcements bool no_init_intersections; }; extern const EmbeddedInterfaceModelOptions default_embedded_interface_model_options; /** * @brief Solid mechanics model using the embedded model. * * This SolidMechanicsModel subclass implements the embedded model, * a method used to represent 1D elements in a finite elements model * (eg. reinforcements in concrete). * * In addition to the SolidMechanicsModel properties, this model has * a mesh of the 1D elements embedded in the model, and an instance of the * EmbeddedInterfaceIntersector class for the computation of the intersections of the * 1D elements with the background (bulk) mesh. * * @see MaterialReinforcement */ class EmbeddedInterfaceModel : public SolidMechanicsModel { /// Same type as SolidMechanicsModel typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular> MyFEEngineType; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: /** * @brief Constructor * * @param mesh main mesh (concrete) * @param primitive_mesh mesh of the embedded reinforcement */ EmbeddedInterfaceModel(Mesh & mesh, Mesh & primitive_mesh, UInt spatial_dimension = _all_dimensions, const ID & id = "embedded_interface_model", const MemoryID & memory_id = 0); /// Destructor virtual ~EmbeddedInterfaceModel(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// Initialise the model virtual void initFull(const ModelOptions & options = default_embedded_interface_model_options); /// Initialise the materials virtual void initMaterials(); /// Allows filtering of dump fields which need to be dumpes on interface mesh virtual void addDumpGroupFieldToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name, const ElementKind & element_kind, bool padding_flag); // virtual ElementTypeMap<UInt> getInternalDataPerElem(const std::string & field_name, // const ElementKind & kind); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// Get interface mesh AKANTU_GET_MACRO(InterfaceMesh, *interface_mesh, Mesh &); /// Get associated elements AKANTU_GET_MACRO_BY_ELEMENT_TYPE(InterfaceAssociatedElements, interface_mesh->getData<Element>("associated_element"), Element); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Intersector object to build the interface mesh EmbeddedInterfaceIntersector intersector; /// Interface mesh (weak reference) Mesh * interface_mesh; /// Mesh used to create the CGAL primitives for intersections Mesh & primitive_mesh; /// Material selector for interface MaterialSelector * interface_material_selector; }; /// Material selector based on mesh data for interface elements template<typename T> class InterfaceMeshDataMaterialSelector : public ElementDataMaterialSelector<T> { public: InterfaceMeshDataMaterialSelector(const std::string & name, const EmbeddedInterfaceModel & model, UInt first_index = 1) : ElementDataMaterialSelector<T>(model.getInterfaceMesh().getData<T>(name), model, first_index) {} }; -__END_AKANTU__ +} // akantu #endif // __AKANTU_EMBEDDED_INTERFACE_MODEL_HH__ diff --git a/src/model/solid_mechanics/solid_mechanics_model_event_handler.hh b/src/model/solid_mechanics/solid_mechanics_model_event_handler.hh index 4adb04969..a51786740 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_event_handler.hh +++ b/src/model/solid_mechanics/solid_mechanics_model_event_handler.hh @@ -1,127 +1,127 @@ /** * @file solid_mechanics_model_event_handler.hh * * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Dec 18 2015 * * @brief EventHandler implementation for SolidMechanicsEvents * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLID_MECHANICS_MODEL_EVENT_HANDLER_HH__ #define __AKANTU_SOLID_MECHANICS_MODEL_EVENT_HANDLER_HH__ -__BEGIN_AKANTU__ +namespace akantu { /// akantu::SolidMechanicsModelEvent is the base event for model namespace SolidMechanicsModelEvent { struct BeforeSolveStepEvent { BeforeSolveStepEvent(AnalysisMethod & method) : method(method) {} AnalysisMethod method; }; struct AfterSolveStepEvent { AfterSolveStepEvent(AnalysisMethod & method) : method(method) {} AnalysisMethod method; }; struct BeforeDumpEvent { BeforeDumpEvent() {} }; struct BeginningOfDamageIterationEvent { BeginningOfDamageIterationEvent() {} }; struct AfterDamageEvent { AfterDamageEvent() {} }; } /// akantu::SolidMechanicsModelEvent class SolidMechanicsModelEventHandler { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: virtual ~SolidMechanicsModelEventHandler(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ protected: /// Send what is before the solve step to the beginning of solve step through /// EventManager inline void sendEvent(const SolidMechanicsModelEvent::BeforeSolveStepEvent & event) { onBeginningSolveStep(event.method); } /// Send what is after the solve step to the end of solve step through /// EventManager inline void sendEvent(const SolidMechanicsModelEvent::AfterSolveStepEvent & event) { onEndSolveStep(event.method); } /// Send what is before dump to current dump through EventManager inline void sendEvent(__attribute__((unused)) const SolidMechanicsModelEvent::BeforeDumpEvent & event) { onDump(); } /// Send what is at the beginning of damage iteration to Damage iteration /// through EventManager inline void sendEvent( __attribute__((unused)) const SolidMechanicsModelEvent::BeginningOfDamageIterationEvent & event) { onDamageIteration(); } /// Send what is after damage for the damage update through EventManager inline void sendEvent(__attribute__((unused)) const SolidMechanicsModelEvent::AfterDamageEvent & event) { onDamageUpdate(); } template <class EventHandler> friend class EventHandlerManager; /* ------------------------------------------------------------------------ */ /* Interface */ /* ------------------------------------------------------------------------ */ public: /// function to implement to react on akantu::BeforeSolveStepEvent virtual void onBeginningSolveStep(__attribute__((unused)) const AnalysisMethod & method) {} /// function to implement to react on akantu::AfterSolveStepEvent virtual void onEndSolveStep(__attribute__((unused)) const AnalysisMethod & method) {} /// function to implement to react on akantu::BeforeDumpEvent virtual void onDump() {} /// function to implement to react on akantu::BeginningOfDamageIterationEvent virtual void onDamageIteration() {} /// function to implement to react on akantu::AfterDamageEvent virtual void onDamageUpdate() {} }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_SOLID_MECHANICS_MODEL_EVENT_HANDLER_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model_mass.cc b/src/model/solid_mechanics/solid_mechanics_model_mass.cc index e4d42481a..d5038332a 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_mass.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_mass.cc @@ -1,190 +1,190 @@ /** * @file solid_mechanics_model_mass.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Oct 05 2010 * @date last modification: Fri Oct 16 2015 * * @brief function handling mass computation * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material.hh" #include "model_solver.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleMassLumped() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); if (this->mass == NULL) { std::stringstream sstr_mass; sstr_mass << id << ":mass"; mass = &(alloc<Real>(sstr_mass.str(), nb_nodes, spatial_dimension, 0)); } else { mass->clear(); } if (!this->getDOFManager().hasLumpedMatrix("M")) { this->getDOFManager().getNewLumpedMatrix("M"); } this->getDOFManager().clearLumpedMatrix("M"); assembleMassLumped(_not_ghost); assembleMassLumped(_ghost); this->getDOFManager().getLumpedMatrixPerDOFs("displacement", "M", *(this->mass)); /// for not connected nodes put mass to one in order to avoid #if !defined(AKANTU_NDEBUG) bool has_unconnected_nodes = false; auto mass_it = mass->begin_reinterpret(mass->getSize() * mass->getNbComponent()); auto mass_end = mass->end_reinterpret(mass->getSize() * mass->getNbComponent()); for (; mass_it != mass_end; ++mass_it) { if (std::abs(*mass_it) < std::numeric_limits<Real>::epsilon() || Math::isnan(*mass_it)) { has_unconnected_nodes = true; break; } } if(has_unconnected_nodes) AKANTU_DEBUG_WARNING("There are nodes that seem to not be connected to any " "elements, beware that they have lumped mass of 0."); #endif this->synchronize(_gst_smm_mass); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleMassLumped(GhostType ghost_type) { AKANTU_DEBUG_IN(); FEEngine & fem = getFEEngine(); Array<Real> rho(0, spatial_dimension); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type); for (; it != end; ++it) { ElementType type = *it; computeRho(rho, type, ghost_type); fem.assembleFieldLumped(rho, "M", "displacement", this->getDOFManager(), type, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleMass() { AKANTU_DEBUG_IN(); if (!this->getDOFManager().hasMatrix("M")) { this->getDOFManager().getNewMatrix("M", "J"); } this->getDOFManager().clearMatrix("M"); assembleMass(_not_ghost); AKANTU_DEBUG_OUT(); } class ComputeRhoFunctor { public: explicit ComputeRhoFunctor(const SolidMechanicsModel & model) : model(model){}; void operator()(Matrix<Real> & rho, const Element & element, __attribute__((unused)) const Matrix<Real> quad_coords) const { const Array<UInt> & mat_indexes = model.getMaterialByElement(element.type, element.ghost_type); Real mat_rho = model.getMaterial(mat_indexes(element.element)).getParam("rho"); rho.set(mat_rho); } private: const SolidMechanicsModel & model; }; /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleMass(GhostType ghost_type) { AKANTU_DEBUG_IN(); MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>(); ComputeRhoFunctor compute_rho(*this); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type); for (; it != end; ++it) { ElementType type = *it; fem.assembleFieldMatrix(compute_rho, "M", "displacement", this->getDOFManager(), type, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::computeRho(Array<Real> & rho, ElementType type, GhostType ghost_type) { AKANTU_DEBUG_IN(); FEEngine & fem = this->getFEEngine(); UInt nb_element = fem.getMesh().getNbElement(type, ghost_type); Array<UInt> & mat_indexes = this->material_index(type, ghost_type); UInt nb_quadrature_points = fem.getNbIntegrationPoints(type); rho.resize(nb_element * nb_quadrature_points); Array<Real>::vector_iterator rho_it = rho.begin(spatial_dimension); /// compute @f$ rho @f$ for each nodes of each element for (UInt el = 0; el < nb_element; ++el) { /// here rho is constant in an element Real mat_rho = this->materials[mat_indexes(el)]->getParam("rho"); for (UInt n = 0; n < nb_quadrature_points; ++n, ++rho_it) { (*rho_it).set(mat_rho); } } AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu diff --git a/src/model/solid_mechanics/solid_mechanics_model_material.cc b/src/model/solid_mechanics/solid_mechanics_model_material.cc index 62cd461f8..a312e323d 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_material.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_material.cc @@ -1,333 +1,333 @@ /** * @file solid_mechanics_model_material.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Nov 26 2010 * @date last modification: Mon Nov 16 2015 * * @brief instatiation of materials * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_math.hh" #include "material_list.hh" #include "solid_mechanics_model.hh" #ifdef AKANTU_DAMAGE_NON_LOCAL #include "non_local_manager.hh" #endif /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ #define AKANTU_INTANTIATE_MATERIAL_BY_DIM_NO_TMPL(dim, elem) \ registerNewMaterial<BOOST_PP_ARRAY_ELEM(1, elem) < dim>> (section) #define AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL_EACH(r, data, i, elem) \ BOOST_PP_EXPR_IF(BOOST_PP_NOT_EQUAL(0, i), else) \ if (opt_param == BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, elem))) { \ registerNewMaterial<BOOST_PP_ARRAY_ELEM(1, data) < \ BOOST_PP_ARRAY_ELEM(0, data), \ BOOST_PP_SEQ_ENUM(BOOST_PP_TUPLE_ELEM(2, 1, elem))>> \ (section); \ } #define AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL(dim, elem) \ BOOST_PP_SEQ_FOR_EACH_I(AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL_EACH, \ (2, (dim, BOOST_PP_ARRAY_ELEM(1, elem))), \ BOOST_PP_ARRAY_ELEM(2, elem)) \ else { \ AKANTU_INTANTIATE_MATERIAL_BY_DIM_NO_TMPL(dim, elem); \ } #define AKANTU_INTANTIATE_MATERIAL_BY_DIM(dim, elem) \ BOOST_PP_IF(BOOST_PP_EQUAL(3, BOOST_PP_ARRAY_SIZE(elem)), \ AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL, \ AKANTU_INTANTIATE_MATERIAL_BY_DIM_NO_TMPL) \ (dim, elem) #define AKANTU_INTANTIATE_MATERIAL(elem) \ switch (spatial_dimension) { \ case 1: { \ AKANTU_INTANTIATE_MATERIAL_BY_DIM(1, elem); \ break; \ } \ case 2: { \ AKANTU_INTANTIATE_MATERIAL_BY_DIM(2, elem); \ break; \ } \ case 3: { \ AKANTU_INTANTIATE_MATERIAL_BY_DIM(3, elem); \ break; \ } \ } #define AKANTU_INTANTIATE_MATERIAL_IF(elem) \ if (mat_type == BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(0, elem))) { \ AKANTU_INTANTIATE_MATERIAL(elem); \ } #define AKANTU_INTANTIATE_OTHER_MATERIAL(r, data, elem) \ else AKANTU_INTANTIATE_MATERIAL_IF(elem) #define AKANTU_INSTANTIATE_MATERIALS() \ do { \ AKANTU_INTANTIATE_MATERIAL_IF(BOOST_PP_SEQ_HEAD(AKANTU_MATERIAL_LIST)) \ BOOST_PP_SEQ_FOR_EACH(AKANTU_INTANTIATE_OTHER_MATERIAL, _, \ BOOST_PP_SEQ_TAIL(AKANTU_MATERIAL_LIST)) \ else { \ if (getStaticParser().isPermissive()) \ AKANTU_DEBUG_INFO("Malformed material file " \ << ": unknown material type '" << mat_type << "'"); \ else \ AKANTU_DEBUG_WARNING("Malformed material file " \ << ": unknown material type " << mat_type \ << ". This is perhaps a user" \ << " defined material ?"); \ } \ } while (0) /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::instantiateMaterials() { std::pair<Parser::const_section_iterator, Parser::const_section_iterator> sub_sect = this->parser->getSubSections(_st_material); Parser::const_section_iterator it = sub_sect.first; for (; it != sub_sect.second; ++it) { const ParserSection & section = *it; std::string mat_type = section.getName(); std::string opt_param = section.getOption(); AKANTU_INSTANTIATE_MATERIALS(); } are_materials_instantiated = true; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assignMaterialToElements( const ElementTypeMapArray<UInt> * filter) { Element element; element.ghost_type = _not_ghost; auto element_types = mesh.elementTypes(spatial_dimension, _not_ghost, _ek_not_defined); if (filter != NULL) { element_types = filter->elementTypes(spatial_dimension, _not_ghost, _ek_not_defined); } // Fill the element material array from the material selector for (auto type : element_types) { UInt nb_element = mesh.getNbElement(type, _not_ghost); const Array<UInt> * filter_array = NULL; if (filter != NULL) { filter_array = &((*filter)(type, _not_ghost)); nb_element = filter_array->getSize(); } element.type = type; element.kind = mesh.getKind(element.type); Array<UInt> & mat_indexes = material_index(type, _not_ghost); for (UInt el = 0; el < nb_element; ++el) { if (filter != NULL) element.element = (*filter_array)(el); else element.element = el; UInt mat_index = (*material_selector)(element); AKANTU_DEBUG_ASSERT( mat_index < materials.size(), "The material selector returned an index that does not exists"); mat_indexes(element.element) = mat_index; } } // synchronize the element material arrays this->synchronize(_gst_material_id); /// fill the element filters of the materials using the element_material /// arrays for (auto ghost_type : ghost_types) { element_types = mesh.elementTypes(spatial_dimension, ghost_type, _ek_not_defined); if (filter != NULL) { element_types = filter->elementTypes(spatial_dimension, ghost_type, _ek_not_defined); } for (auto type : element_types) { UInt nb_element = mesh.getNbElement(type, ghost_type); const Array<UInt> * filter_array = NULL; if (filter != NULL) { filter_array = &((*filter)(type, ghost_type)); nb_element = filter_array->getSize(); } Array<UInt> & mat_indexes = material_index(type, ghost_type); Array<UInt> & mat_local_num = material_local_numbering(type, ghost_type); for (UInt el = 0; el < nb_element; ++el) { UInt element; if (filter != NULL) element = (*filter_array)(el); else element = el; UInt mat_index = mat_indexes(element); UInt index = materials[mat_index]->addElement(type, element, ghost_type); mat_local_num(element) = index; } } } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initMaterials() { AKANTU_DEBUG_ASSERT(materials.size() != 0, "No material to initialize !"); if (!are_materials_instantiated) instantiateMaterials(); this->assignMaterialToElements(); for (auto & material : materials) { /// init internals properties material->initMaterial(); } this->synchronize(_gst_smm_init_mat); // initialize mass switch (method) { case _explicit_lumped_mass: assembleMassLumped(); break; case _explicit_consistent_mass: case _implicit_dynamic: assembleMass(); break; case _static: break; default: AKANTU_EXCEPTION("analysis method not recognised by SolidMechanicsModel"); break; } // initialize the previous displacement array if at least on material needs it // for (auto & material : materials) { // if (material->isFiniteDeformation() || material->isInelasticDeformation()) { // initArraysPreviousDisplacment(); // break; // } // } #ifdef AKANTU_DAMAGE_NON_LOCAL /// initialize the non-local manager for non-local computations this->non_local_manager->init(); #endif } /* -------------------------------------------------------------------------- */ Int SolidMechanicsModel::getInternalIndexFromID(const ID & id) const { AKANTU_DEBUG_IN(); auto it = materials.begin(); auto end = materials.end(); for (; it != end; ++it) if ((*it)->getID() == id) { AKANTU_DEBUG_OUT(); return (it - materials.begin()); } AKANTU_DEBUG_OUT(); return -1; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::reassignMaterial() { AKANTU_DEBUG_IN(); std::vector<Array<Element>> element_to_add(materials.size()); std::vector<Array<Element>> element_to_remove(materials.size()); Element element; for (auto ghost_type : ghost_types) { element.ghost_type = ghost_type; for (auto type : mesh.elementTypes(spatial_dimension, ghost_type, _ek_not_defined)) { element.type = type; element.kind = Mesh::getKind(type); UInt nb_element = mesh.getNbElement(type, ghost_type); Array<UInt> & mat_indexes = material_index(type, ghost_type); for (UInt el = 0; el < nb_element; ++el) { element.element = el; UInt old_material = mat_indexes(el); UInt new_material = (*material_selector)(element); if (old_material != new_material) { element_to_add[new_material].push_back(element); element_to_remove[old_material].push_back(element); } } } } UInt mat_index = 0; for (auto mat_it = materials.begin(); mat_it != materials.end(); ++mat_it, ++mat_index) { (*mat_it)->removeElements(element_to_remove[mat_index]); (*mat_it)->addElements(element_to_add[mat_index]); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::applyEigenGradU( const Matrix<Real> & prescribed_eigen_grad_u, const ID & material_name, const GhostType ghost_type) { AKANTU_DEBUG_ASSERT(prescribed_eigen_grad_u.size() == spatial_dimension * spatial_dimension, "The prescribed grad_u is not of the good size"); for (auto & material : materials) { if (material->getName() == material_name) material->applyEigenGradU(prescribed_eigen_grad_u, ghost_type); } } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/solver_callback.cc b/src/model/solver_callback.cc index feb2b69f6..321fdbbcf 100644 --- a/src/model/solver_callback.cc +++ b/src/model/solver_callback.cc @@ -1,63 +1,63 @@ /** * @file solver_callback.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Wed Mar 2 12:47:17 2016 * * @brief Default behavior of solver_callbacks * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "solver_callback.hh" #include "dof_manager.hh" -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ SolverCallback::SolverCallback(DOFManager & dof_manager) : sc_dof_manager(&dof_manager) {} /* -------------------------------------------------------------------------- */ SolverCallback::SolverCallback() : sc_dof_manager(NULL) {} /* -------------------------------------------------------------------------- */ SolverCallback::~SolverCallback() {} /* -------------------------------------------------------------------------- */ void SolverCallback::setDOFManager(DOFManager & dof_manager) { this->sc_dof_manager = &dof_manager; } /* -------------------------------------------------------------------------- */ void SolverCallback::assembleJacobian() { this->sc_dof_manager->clearMatrix("J"); } /* -------------------------------------------------------------------------- */ void SolverCallback::assembleResidual() { this->sc_dof_manager->clearResidual(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/solver_callback.hh b/src/model/solver_callback.hh index 702989340..c182a10dd 100644 --- a/src/model/solver_callback.hh +++ b/src/model/solver_callback.hh @@ -1,83 +1,83 @@ /** * @file solver_callback.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Tue Sep 15 22:45:27 2015 * * @brief Class defining the interface for non_linear_solver callbacks * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLVER_CALLBACK_HH__ #define __AKANTU_SOLVER_CALLBACK_HH__ namespace akantu { class DOFManager; } -__BEGIN_AKANTU__ +namespace akantu { class SolverCallback { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: explicit SolverCallback(DOFManager & dof_manager); explicit SolverCallback(); /* ------------------------------------------------------------------------ */ virtual ~SolverCallback(); protected: void setDOFManager(DOFManager & dof_manager); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// callback to assemble the Jacobian Matrix virtual void assembleJacobian(); /// callback to assemble the residual (rhs) virtual void assembleResidual(); /* ------------------------------------------------------------------------ */ /* Dynamic simulations part */ /* ------------------------------------------------------------------------ */ /// callback for the predictor (in case of dynamic simulation) virtual void predictor() { AKANTU_DEBUG_TO_IMPLEMENT(); } /// callback for the corrector (in case of dynamic simulation) virtual void corrector() { AKANTU_DEBUG_TO_IMPLEMENT(); } protected: /// DOFManager prefixed to avoid collision in multiple inheritance cases DOFManager * sc_dof_manager; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_SOLVER_CALLBACK_HH__ */ diff --git a/src/model/structural_mechanics/structural_mechanics_model.cc b/src/model/structural_mechanics/structural_mechanics_model.cc index 531b7bdce..52168fe3c 100644 --- a/src/model/structural_mechanics/structural_mechanics_model.cc +++ b/src/model/structural_mechanics/structural_mechanics_model.cc @@ -1,1225 +1,1225 @@ /** * @file structural_mechanics_model.cc * * @author Fabian Barras <fabian.barras@epfl.ch> * @author Sébastien Hartmann <sebastien.hartmann@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Damien Spielmann <damien.spielmann@epfl.ch> * * @date creation: Fri Jul 15 2011 * @date last modification: Thu Oct 15 2015 * * @brief Model implementation for StucturalMechanics elements * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "structural_mechanics_model.hh" #include "group_manager_inline_impl.cc" #include "dumpable_inline_impl.hh" #include "aka_math.hh" #include "integration_scheme_2nd_order.hh" #include "static_communicator.hh" #include "sparse_matrix.hh" #include "solver.hh" #ifdef AKANTU_USE_MUMPS #include "solver_mumps.hh" #endif #ifdef AKANTU_USE_IOHELPER #include "dumper_paraview.hh" #include "dumper_elemental_field.hh" #endif /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { const StructuralMechanicsModelOptions default_structural_mechanics_model_options(_static); /* -------------------------------------------------------------------------- */ StructuralMechanicsModel::StructuralMechanicsModel(Mesh & mesh, UInt dim, const ID & id, const MemoryID & memory_id) : Model(mesh, dim, id, memory_id), time_step(NAN), f_m2a(1.0), stress("stress", id, memory_id), element_material("element_material", id, memory_id), set_ID("beam sets", id, memory_id), stiffness_matrix(NULL), mass_matrix(NULL), velocity_damping_matrix(NULL), jacobian_matrix(NULL), solver(NULL), rotation_matrix("rotation_matices", id, memory_id), increment_flag(false), integrator(NULL) { AKANTU_DEBUG_IN(); registerFEEngineObject<MyFEEngineType>("StructuralMechanicsFEEngine", mesh, spatial_dimension); this->displacement_rotation = NULL; this->mass = NULL; this->velocity = NULL; this->acceleration = NULL; this->force_momentum = NULL; this->residual = NULL; this->blocked_dofs = NULL; this->increment = NULL; this->previous_displacement = NULL; if (spatial_dimension == 2) nb_degree_of_freedom = 3; else if (spatial_dimension == 3) nb_degree_of_freedom = 6; else { AKANTU_DEBUG_TO_IMPLEMENT(); } this->mesh.registerDumper<DumperParaview>("paraview_all", id, true); this->mesh.addDumpMesh(mesh, spatial_dimension, _not_ghost, _ek_structural); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ StructuralMechanicsModel::~StructuralMechanicsModel() { AKANTU_DEBUG_IN(); delete integrator; delete solver; delete stiffness_matrix; delete jacobian_matrix; delete mass_matrix; delete velocity_damping_matrix; AKANTU_DEBUG_OUT(); } void StructuralMechanicsModel::setTimeStep(Real time_step) { this->time_step = time_step; #if defined(AKANTU_USE_IOHELPER) this->mesh.getDumper().setTimeStep(time_step); #endif } /* -------------------------------------------------------------------------- */ /* Initialisation */ /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::initFull(const ModelOptions & options) { const StructuralMechanicsModelOptions & stmm_options = dynamic_cast<const StructuralMechanicsModelOptions &>(options); method = stmm_options.analysis_method; initModel(); initArrays(); displacement_rotation->clear(); velocity->clear(); acceleration->clear(); force_momentum->clear(); residual->clear(); blocked_dofs->clear(); increment->clear(); Mesh::type_iterator it = getFEEngine().getMesh().firstType( spatial_dimension, _not_ghost, _ek_structural); Mesh::type_iterator end = getFEEngine().getMesh().lastType( spatial_dimension, _not_ghost, _ek_structural); for (; it != end; ++it) { computeRotationMatrix(*it); } switch (method) { case _implicit_dynamic: initImplicit(); break; case _static: initSolver(); break; default: AKANTU_EXCEPTION( "analysis method not recognised by StructuralMechanicsModel"); break; } } /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::initArrays() { AKANTU_DEBUG_IN(); UInt nb_nodes = getFEEngine().getMesh().getNbNodes(); std::stringstream sstr_disp; sstr_disp << id << ":displacement"; 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 << ":blocked_dofs"; std::stringstream sstr_incr; sstr_incr << id << ":increment"; displacement_rotation = &(alloc<Real>(sstr_disp.str(), nb_nodes, nb_degree_of_freedom, REAL_INIT_VALUE)); velocity = &(alloc<Real>(sstr_velo.str(), nb_nodes, nb_degree_of_freedom, REAL_INIT_VALUE)); acceleration = &(alloc<Real>(sstr_acce.str(), nb_nodes, nb_degree_of_freedom, REAL_INIT_VALUE)); force_momentum = &(alloc<Real>(sstr_forc.str(), nb_nodes, nb_degree_of_freedom, REAL_INIT_VALUE)); residual = &(alloc<Real>(sstr_resi.str(), nb_nodes, nb_degree_of_freedom, REAL_INIT_VALUE)); blocked_dofs = &(alloc<bool>(sstr_boun.str(), nb_nodes, nb_degree_of_freedom, false)); increment = &(alloc<Real>(sstr_incr.str(), nb_nodes, nb_degree_of_freedom, REAL_INIT_VALUE)); Mesh::type_iterator it = getFEEngine().getMesh().firstType( spatial_dimension, _not_ghost, _ek_structural); Mesh::type_iterator end = getFEEngine().getMesh().lastType( spatial_dimension, _not_ghost, _ek_structural); for (; it != end; ++it) { UInt nb_element = getFEEngine().getMesh().getNbElement(*it); UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(*it); element_material.alloc(nb_element, 1, *it, _not_ghost); set_ID.alloc(nb_element, 1, *it, _not_ghost); UInt size = getTangentStiffnessVoigtSize(*it); stress.alloc(nb_element * nb_quadrature_points, size, *it, _not_ghost); } dof_synchronizer = new DOFSynchronizer(getFEEngine().getMesh(), nb_degree_of_freedom); dof_synchronizer->initLocalDOFEquationNumbers(); dof_synchronizer->initGlobalDOFEquationNumbers(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::initModel() { getFEEngine().initShapeFunctions(_not_ghost); } /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::initSolver(__attribute__((unused)) SolverOptions & options) { AKANTU_DEBUG_IN(); const Mesh & mesh = getFEEngine().getMesh(); #if !defined(AKANTU_USE_MUMPS) // or other solver in the future \todo add // AKANTU_HAS_SOLVER in CMake AKANTU_DEBUG_ERROR("You should at least activate one solver."); #else UInt nb_global_node = mesh.getNbGlobalNodes(); std::stringstream sstr; sstr << id << ":jacobian_matrix"; jacobian_matrix = new SparseMatrix(nb_global_node * nb_degree_of_freedom, _symmetric, sstr.str(), memory_id); jacobian_matrix->buildProfile(mesh, *dof_synchronizer, nb_degree_of_freedom); std::stringstream sstr_sti; sstr_sti << id << ":stiffness_matrix"; stiffness_matrix = new SparseMatrix(*jacobian_matrix, sstr_sti.str(), memory_id); #ifdef AKANTU_USE_MUMPS std::stringstream sstr_solv; sstr_solv << id << ":solver"; solver = new SolverMumps(*jacobian_matrix, sstr_solv.str()); dof_synchronizer->initScatterGatherCommunicationScheme(); #else AKANTU_DEBUG_ERROR("You should at least activate one solver."); #endif // AKANTU_USE_MUMPS solver->initialize(options); #endif // AKANTU_HAS_SOLVER AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::initImplicit( __attribute__((unused)) bool dynamic, SolverOptions & solver_options) { AKANTU_DEBUG_IN(); if (!increment) setIncrementFlagOn(); initSolver(solver_options); if (integrator) delete integrator; integrator = new TrapezoidalRule2(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ UInt StructuralMechanicsModel::getTangentStiffnessVoigtSize( const ElementType & type) { UInt size; #define GET_TANGENT_STIFFNESS_VOIGT_SIZE(type) \ size = getTangentStiffnessVoigtSize<type>(); AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(GET_TANGENT_STIFFNESS_VOIGT_SIZE); #undef GET_TANGENT_STIFFNESS_VOIGT_SIZE return size; } /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::assembleStiffnessMatrix() { AKANTU_DEBUG_IN(); stiffness_matrix->clear(); Mesh::type_iterator it = getFEEngine().getMesh().firstType( spatial_dimension, _not_ghost, _ek_structural); Mesh::type_iterator end = getFEEngine().getMesh().lastType( spatial_dimension, _not_ghost, _ek_structural); for (; it != end; ++it) { ElementType type = *it; #define ASSEMBLE_STIFFNESS_MATRIX(type) assembleStiffnessMatrix<type>(); AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(ASSEMBLE_STIFFNESS_MATRIX); #undef ASSEMBLE_STIFFNESS_MATRIX } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> void StructuralMechanicsModel::computeRotationMatrix<_bernoulli_beam_2>( Array<Real> & rotations) { ElementType type = _bernoulli_beam_2; Mesh & mesh = getFEEngine().getMesh(); UInt nb_element = mesh.getNbElement(type); Array<UInt>::iterator<Vector<UInt> > connec_it = mesh.getConnectivity(type).begin(2); Array<Real>::vector_iterator nodes_it = mesh.getNodes().begin(spatial_dimension); Array<Real>::matrix_iterator R_it = rotations.begin(nb_degree_of_freedom, nb_degree_of_freedom); for (UInt e = 0; e < nb_element; ++e, ++R_it, ++connec_it) { Matrix<Real> & R = *R_it; Vector<UInt> & connec = *connec_it; Vector<Real> x2; x2 = nodes_it[connec(1)]; // X2 Vector<Real> x1; x1 = nodes_it[connec(0)]; // X1 Real le = x1.distance(x2); Real c = (x2(0) - x1(0)) / le; Real s = (x2(1) - x1(1)) / le; /// Definition of the rotation matrix R(0, 0) = c; R(0, 1) = s; R(0, 2) = 0.; R(1, 0) = -s; R(1, 1) = c; R(1, 2) = 0.; R(2, 0) = 0.; R(2, 1) = 0.; R(2, 2) = 1.; } } /* -------------------------------------------------------------------------- */ template <> void StructuralMechanicsModel::computeRotationMatrix<_bernoulli_beam_3>( Array<Real> & rotations) { ElementType type = _bernoulli_beam_3; Mesh & mesh = getFEEngine().getMesh(); UInt nb_element = mesh.getNbElement(type); Array<Real>::vector_iterator n_it = mesh.getNormals(type).begin(spatial_dimension); Array<UInt>::iterator<Vector<UInt> > connec_it = mesh.getConnectivity(type).begin(2); Array<Real>::vector_iterator nodes_it = mesh.getNodes().begin(spatial_dimension); Matrix<Real> Pe(spatial_dimension, spatial_dimension); Matrix<Real> Pg(spatial_dimension, spatial_dimension); Matrix<Real> inv_Pg(spatial_dimension, spatial_dimension); Vector<Real> x_n(spatial_dimension); // x vect n Array<Real>::matrix_iterator R_it = rotations.begin(nb_degree_of_freedom, nb_degree_of_freedom); for (UInt e = 0; e < nb_element; ++e, ++n_it, ++connec_it, ++R_it) { Vector<Real> & n = *n_it; Matrix<Real> & R = *R_it; Vector<UInt> & connec = *connec_it; Vector<Real> x; x = nodes_it[connec(1)]; // X2 Vector<Real> y; y = nodes_it[connec(0)]; // X1 Real l = x.distance(y); x -= y; // X2 - X1 x_n.crossProduct(x, n); Pe.eye(); Pe(0, 0) *= l; Pe(1, 1) *= -l; Pg(0, 0) = x(0); Pg(0, 1) = x_n(0); Pg(0, 2) = n(0); Pg(1, 0) = x(1); Pg(1, 1) = x_n(1); Pg(1, 2) = n(1); Pg(2, 0) = x(2); Pg(2, 1) = x_n(2); Pg(2, 2) = n(2); inv_Pg.inverse(Pg); Pe *= inv_Pg; for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < spatial_dimension; ++j) { R(i, j) = Pe(i, j); R(i + spatial_dimension, j + spatial_dimension) = Pe(i, j); } } } } /* -------------------------------------------------------------------------- */ template <> void StructuralMechanicsModel::computeRotationMatrix<_kirchhoff_shell>( Array<Real> & rotations) { ElementType type = _kirchhoff_shell; Mesh & mesh = getFEEngine().getMesh(); UInt nb_element = mesh.getNbElement(type); Array<UInt>::iterator<Vector<UInt> > connec_it = mesh.getConnectivity(type).begin(3); Array<Real>::vector_iterator nodes_it = mesh.getNodes().begin(spatial_dimension); Matrix<Real> Pe(spatial_dimension, spatial_dimension); Matrix<Real> Pg(spatial_dimension, spatial_dimension); Matrix<Real> inv_Pg(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator R_it = rotations.begin(nb_degree_of_freedom, nb_degree_of_freedom); for (UInt e = 0; e < nb_element; ++e, ++connec_it, ++R_it) { Pe.eye(); Matrix<Real> & R = *R_it; Vector<UInt> & connec = *connec_it; Vector<Real> x2; x2 = nodes_it[connec(1)]; // X2 Vector<Real> x1; x1 = nodes_it[connec(0)]; // X1 Vector<Real> x3; x3 = nodes_it[connec(2)]; // X3 Vector<Real> Pg_col_1 = x2 - x1; Vector<Real> Pg_col_2 = x3 - x1; Vector<Real> Pg_col_3(spatial_dimension); Pg_col_3.crossProduct(Pg_col_1, Pg_col_2); for (UInt i = 0; i < spatial_dimension; ++i) { Pg(i, 0) = Pg_col_1(i); Pg(i, 1) = Pg_col_2(i); Pg(i, 2) = Pg_col_3(i); } inv_Pg.inverse(Pg); // Pe *= inv_Pg; Pe.eye(); for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < spatial_dimension; ++j) { R(i, j) = Pe(i, j); R(i + spatial_dimension, j + spatial_dimension) = Pe(i, j); } } } } /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::computeRotationMatrix(const ElementType & type) { Mesh & mesh = getFEEngine().getMesh(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_element = mesh.getNbElement(type); if (!rotation_matrix.exists(type)) { rotation_matrix.alloc(nb_element, nb_degree_of_freedom * nb_nodes_per_element * nb_degree_of_freedom * nb_nodes_per_element, type); } else { rotation_matrix(type).resize(nb_element); } rotation_matrix(type).clear(); Array<Real> rotations(nb_element, nb_degree_of_freedom * nb_degree_of_freedom); rotations.clear(); #define COMPUTE_ROTATION_MATRIX(type) computeRotationMatrix<type>(rotations); AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(COMPUTE_ROTATION_MATRIX); #undef COMPUTE_ROTATION_MATRIX Array<Real>::matrix_iterator R_it = rotations.begin(nb_degree_of_freedom, nb_degree_of_freedom); Array<Real>::matrix_iterator T_it = rotation_matrix(type).begin(nb_degree_of_freedom * nb_nodes_per_element, nb_degree_of_freedom * nb_nodes_per_element); for (UInt el = 0; el < nb_element; ++el, ++R_it, ++T_it) { Matrix<Real> & T = *T_it; Matrix<Real> & R = *R_it; T.clear(); for (UInt k = 0; k < nb_nodes_per_element; ++k) { for (UInt i = 0; i < nb_degree_of_freedom; ++i) for (UInt j = 0; j < nb_degree_of_freedom; ++j) T(k * nb_degree_of_freedom + i, k * nb_degree_of_freedom + j) = R(i, j); } } } /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::computeStresses() { AKANTU_DEBUG_IN(); Mesh::type_iterator it = getFEEngine().getMesh().firstType( spatial_dimension, _not_ghost, _ek_structural); Mesh::type_iterator end = getFEEngine().getMesh().lastType( spatial_dimension, _not_ghost, _ek_structural); for (; it != end; ++it) { ElementType type = *it; #define COMPUTE_STRESS_ON_QUAD(type) computeStressOnQuad<type>(); AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(COMPUTE_STRESS_ON_QUAD); #undef COMPUTE_STRESS_ON_QUAD } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::updateResidual() { AKANTU_DEBUG_IN(); residual->copy(*force_momentum); Array<Real> ku(*displacement_rotation, true); ku *= *stiffness_matrix; *residual -= ku; this->updateResidualInternal(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::implicitPred() { AKANTU_DEBUG_IN(); if (previous_displacement) previous_displacement->copy(*displacement_rotation); if (method == _implicit_dynamic) integrator->integrationSchemePred(time_step, *displacement_rotation, *velocity, *acceleration, *blocked_dofs); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::implicitCorr() { AKANTU_DEBUG_IN(); Real * incr_val = increment->storage(); bool * boun_val = blocked_dofs->storage(); UInt nb_nodes = displacement_rotation->getSize(); for (UInt j = 0; j < nb_nodes * nb_degree_of_freedom; ++j, ++incr_val, ++boun_val) { *incr_val *= (1. - *boun_val); } if (method == _implicit_dynamic) { integrator->integrationSchemeCorrDispl(time_step, *displacement_rotation, *velocity, *acceleration, *blocked_dofs, *increment); } else { Real * disp_val = displacement_rotation->storage(); incr_val = increment->storage(); for (UInt j = 0; j < nb_nodes * nb_degree_of_freedom; ++j, ++disp_val, ++incr_val) { *disp_val += *incr_val; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::updateResidualInternal() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Update the residual"); // f = f_ext - f_int - Ma - Cv = r - Ma - Cv; if (method != _static) { // f -= Ma if (mass_matrix) { // if full mass_matrix Array<Real> * Ma = new Array<Real>(*acceleration, true, "Ma"); *Ma *= *mass_matrix; /// \todo check unit conversion for implicit dynamics // *Ma /= f_m2a *residual -= *Ma; delete Ma; } else if (mass) { // else lumped mass UInt nb_nodes = acceleration->getSize(); UInt nb_degree_of_freedom = acceleration->getNbComponent(); Real * mass_val = mass->storage(); Real * accel_val = acceleration->storage(); Real * res_val = residual->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) { if (!(*blocked_dofs_val)) { *res_val -= *accel_val ** mass_val / f_m2a; } blocked_dofs_val++; res_val++; mass_val++; accel_val++; } } else { AKANTU_DEBUG_ERROR("No function called to assemble the mass matrix."); } // f -= Cv if (velocity_damping_matrix) { Array<Real> * Cv = new Array<Real>(*velocity); *Cv *= *velocity_damping_matrix; *residual -= *Cv; delete Cv; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::setIncrementFlagOn() { AKANTU_DEBUG_IN(); if (!increment) { UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_inc; sstr_inc << id << ":increment"; increment = &(alloc<Real>(sstr_inc.str(), nb_nodes, spatial_dimension, 0.)); } increment_flag = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::solve() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Solving an implicit step."); UInt nb_nodes = displacement_rotation->getSize(); /// todo residual = force - Kxr * d_bloq jacobian_matrix->copyContent(*stiffness_matrix); jacobian_matrix->applyBoundary(*blocked_dofs); jacobian_matrix->saveMatrix("Kbound.mtx"); increment->clear(); solver->setRHS(*residual); solver->factorize(); solver->solve(*increment); Real * increment_val = increment->storage(); Real * displacement_val = displacement_rotation->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) { if (!(*blocked_dofs_val)) { *displacement_val += *increment_val; } else { *increment_val = 0.0; } displacement_val++; blocked_dofs_val++; increment_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> bool StructuralMechanicsModel::testConvergence<_scc_increment>(Real tolerance, Real & error) { AKANTU_DEBUG_IN(); UInt nb_nodes = displacement_rotation->getSize(); UInt nb_degree_of_freedom = displacement_rotation->getNbComponent(); error = 0; Real norm[2] = {0., 0.}; Real * increment_val = increment->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); Real * displacement_val = displacement_rotation->storage(); for (UInt n = 0; n < nb_nodes; ++n) { for (UInt d = 0; d < nb_degree_of_freedom; ++d) { if (!(*blocked_dofs_val)) { norm[0] += *increment_val * *increment_val; norm[1] += *displacement_val * *displacement_val; } blocked_dofs_val++; increment_val++; displacement_val++; } } StaticCommunicator::getStaticCommunicator().allReduce(norm, 2, _so_sum); norm[0] = sqrt(norm[0]); norm[1] = sqrt(norm[1]); AKANTU_DEBUG_ASSERT(!Math::isnan(norm[0]), "Something went wrong in the solve phase"); AKANTU_DEBUG_OUT(); if (norm[1] > Math::getTolerance()) error = norm[0] / norm[1]; else error = norm[0]; // In case the total displacement is zero! return (error < tolerance); } /* -------------------------------------------------------------------------- */ template <> bool StructuralMechanicsModel::testConvergence<_scc_residual>(Real tolerance, Real & norm) { AKANTU_DEBUG_IN(); UInt nb_nodes = residual->getSize(); norm = 0; Real * residual_val = residual->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); for (UInt n = 0; n < nb_nodes; ++n) { bool is_local_node = mesh.isLocalOrMasterNode(n); if (is_local_node) { for (UInt d = 0; d < nb_degree_of_freedom; ++d) { if (!(*blocked_dofs_val)) { norm += *residual_val * *residual_val; } blocked_dofs_val++; residual_val++; } } else { blocked_dofs_val += spatial_dimension; residual_val += spatial_dimension; } } StaticCommunicator::getStaticCommunicator().allReduce(&norm, 1, _so_sum); norm = sqrt(norm); AKANTU_DEBUG_ASSERT(!Math::isnan(norm), "Something goes wrong in the solve phase"); AKANTU_DEBUG_OUT(); return (norm < tolerance); } /* -------------------------------------------------------------------------- */ bool StructuralMechanicsModel::testConvergenceIncrement(Real tolerance) { Real error; bool tmp = testConvergenceIncrement(tolerance, error); AKANTU_DEBUG_INFO("Norm of increment : " << error); return tmp; } /* -------------------------------------------------------------------------- */ bool StructuralMechanicsModel::testConvergenceIncrement(Real tolerance, Real & error) { AKANTU_DEBUG_IN(); Mesh & mesh = getFEEngine().getMesh(); UInt nb_nodes = displacement_rotation->getSize(); UInt nb_degree_of_freedom = displacement_rotation->getNbComponent(); Real norm = 0; Real * increment_val = increment->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); for (UInt n = 0; n < nb_nodes; ++n) { bool is_local_node = mesh.isLocalOrMasterNode(n); for (UInt d = 0; d < nb_degree_of_freedom; ++d) { if (!(*blocked_dofs_val) && is_local_node) { norm += *increment_val * *increment_val; } blocked_dofs_val++; increment_val++; } } StaticCommunicator::getStaticCommunicator().allReduce(&norm, 1, _so_sum); error = sqrt(norm); AKANTU_DEBUG_ASSERT(!Math::isnan(norm), "Something goes wrong in the solve phase"); AKANTU_DEBUG_OUT(); return (error < tolerance); } /* -------------------------------------------------------------------------- */ template <> void StructuralMechanicsModel::computeTangentModuli<_bernoulli_beam_2>( Array<Real> & tangent_moduli) { UInt nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_2); UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(_bernoulli_beam_2); UInt tangent_size = 2; Array<Real>::matrix_iterator D_it = tangent_moduli.begin(tangent_size, tangent_size); Array<UInt> & el_mat = element_material(_bernoulli_beam_2, _not_ghost); for (UInt e = 0; e < nb_element; ++e) { UInt mat = el_mat(e); Real E = materials[mat].E; Real A = materials[mat].A; Real I = materials[mat].I; for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_it) { Matrix<Real> & D = *D_it; D(0, 0) = E * A; D(1, 1) = E * I; } } } /* -------------------------------------------------------------------------- */ template <> void StructuralMechanicsModel::computeTangentModuli<_bernoulli_beam_3>( Array<Real> & tangent_moduli) { UInt nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_3); UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(_bernoulli_beam_3); UInt tangent_size = 4; Array<Real>::matrix_iterator D_it = tangent_moduli.begin(tangent_size, tangent_size); for (UInt e = 0; e < nb_element; ++e) { UInt mat = element_material(_bernoulli_beam_3, _not_ghost)(e); Real E = materials[mat].E; Real A = materials[mat].A; Real Iz = materials[mat].Iz; Real Iy = materials[mat].Iy; Real GJ = materials[mat].GJ; for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_it) { Matrix<Real> & D = *D_it; D(0, 0) = E * A; D(1, 1) = E * Iz; D(2, 2) = E * Iy; D(3, 3) = GJ; } } } /* -------------------------------------------------------------------------- */ template <> void StructuralMechanicsModel::computeTangentModuli<_kirchhoff_shell>( Array<Real> & tangent_moduli) { UInt nb_element = getFEEngine().getMesh().getNbElement(_kirchhoff_shell); UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(_kirchhoff_shell); UInt tangent_size = 6; Array<Real>::matrix_iterator D_it = tangent_moduli.begin(tangent_size, tangent_size); for (UInt e = 0; e < nb_element; ++e) { UInt mat = element_material(_kirchhoff_shell, _not_ghost)(e); Real E = materials[mat].E; Real nu = materials[mat].nu; Real t = materials[mat].t; Real HH = E * t / (1 - nu * nu); Real DD = E * t * t * t / (12 * (1 - nu * nu)); for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_it) { Matrix<Real> & D = *D_it; D(0, 0) = HH; D(0, 1) = HH * nu; D(1, 0) = HH * nu; D(1, 1) = HH; D(2, 2) = HH * (1 - nu) / 2; D(3, 3) = DD; D(3, 4) = DD * nu; D(4, 3) = DD * nu; D(4, 4) = DD; D(5, 5) = DD * (1 - nu) / 2; } } } /* -------------------------------------------------------------------------- */ template <> void StructuralMechanicsModel::transferBMatrixToSymVoigtBMatrix< _bernoulli_beam_2>(Array<Real> & b, __attribute__((unused)) bool local) { UInt nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_2); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(_bernoulli_beam_2); UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(_bernoulli_beam_2); MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>(); Array<Real>::const_vector_iterator shape_Np = fem.getShapesDerivatives(_bernoulli_beam_2, _not_ghost, 0) .begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Mpp = fem.getShapesDerivatives(_bernoulli_beam_2, _not_ghost, 1) .begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Lpp = fem.getShapesDerivatives(_bernoulli_beam_2, _not_ghost, 2) .begin(nb_nodes_per_element); UInt tangent_size = getTangentStiffnessVoigtSize<_bernoulli_beam_2>(); UInt bt_d_b_size = nb_nodes_per_element * nb_degree_of_freedom; b.clear(); Array<Real>::matrix_iterator B_it = b.begin(tangent_size, bt_d_b_size); for (UInt e = 0; e < nb_element; ++e) { for (UInt q = 0; q < nb_quadrature_points; ++q) { Matrix<Real> & B = *B_it; const Vector<Real> & Np = *shape_Np; const Vector<Real> & Lpp = *shape_Lpp; const Vector<Real> & Mpp = *shape_Mpp; B(0, 0) = Np(0); B(0, 3) = Np(1); B(1, 1) = Mpp(0); B(1, 2) = Lpp(0); B(1, 4) = Mpp(1); B(1, 5) = Lpp(1); ++B_it; ++shape_Np; ++shape_Mpp; ++shape_Lpp; } // ++R_it; } } /* -------------------------------------------------------------------------- */ template <> void StructuralMechanicsModel::transferBMatrixToSymVoigtBMatrix< _bernoulli_beam_3>(Array<Real> & b, __attribute__((unused)) bool local) { MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>(); UInt nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_3); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(_bernoulli_beam_3); UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(_bernoulli_beam_3); Array<Real>::const_vector_iterator shape_Np = fem.getShapesDerivatives(_bernoulli_beam_3, _not_ghost, 0) .begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Mpp = fem.getShapesDerivatives(_bernoulli_beam_3, _not_ghost, 1) .begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Lpp = fem.getShapesDerivatives(_bernoulli_beam_3, _not_ghost, 2) .begin(nb_nodes_per_element); UInt tangent_size = getTangentStiffnessVoigtSize<_bernoulli_beam_3>(); UInt bt_d_b_size = nb_nodes_per_element * nb_degree_of_freedom; b.clear(); Array<Real>::matrix_iterator B_it = b.begin(tangent_size, bt_d_b_size); for (UInt e = 0; e < nb_element; ++e) { for (UInt q = 0; q < nb_quadrature_points; ++q) { Matrix<Real> & B = *B_it; const Vector<Real> & Np = *shape_Np; const Vector<Real> & Lpp = *shape_Lpp; const Vector<Real> & Mpp = *shape_Mpp; B(0, 0) = Np(0); B(0, 6) = Np(1); B(1, 1) = Mpp(0); B(1, 5) = Lpp(0); B(1, 7) = Mpp(1); B(1, 11) = Lpp(1); B(2, 2) = Mpp(0); B(2, 4) = -Lpp(0); B(2, 8) = Mpp(1); B(2, 10) = -Lpp(1); B(3, 3) = Np(0); B(3, 9) = Np(1); ++B_it; ++shape_Np; ++shape_Mpp; ++shape_Lpp; } } } /* -------------------------------------------------------------------------- */ template <> void StructuralMechanicsModel::transferBMatrixToSymVoigtBMatrix< _kirchhoff_shell>(Array<Real> & b, __attribute__((unused)) bool local) { MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>(); UInt nb_element = getFEEngine().getMesh().getNbElement(_kirchhoff_shell); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(_kirchhoff_shell); UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(_kirchhoff_shell); Array<Real>::const_matrix_iterator shape_Np = fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 0) .begin(2, nb_nodes_per_element); Array<Real>::const_matrix_iterator shape_Nx1p = fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 1) .begin(2, nb_nodes_per_element); Array<Real>::const_matrix_iterator shape_Nx2p = fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 2) .begin(2, nb_nodes_per_element); Array<Real>::const_matrix_iterator shape_Nx3p = fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 3) .begin(2, nb_nodes_per_element); Array<Real>::const_matrix_iterator shape_Ny1p = fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 4) .begin(2, nb_nodes_per_element); Array<Real>::const_matrix_iterator shape_Ny2p = fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 5) .begin(2, nb_nodes_per_element); Array<Real>::const_matrix_iterator shape_Ny3p = fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 6) .begin(2, nb_nodes_per_element); UInt tangent_size = getTangentStiffnessVoigtSize<_kirchhoff_shell>(); UInt bt_d_b_size = nb_nodes_per_element * nb_degree_of_freedom; b.clear(); Array<Real>::matrix_iterator B_it = b.begin(tangent_size, bt_d_b_size); for (UInt e = 0; e < nb_element; ++e) { for (UInt q = 0; q < nb_quadrature_points; ++q) { Matrix<Real> & B = *B_it; const Matrix<Real> & Np = *shape_Np; const Matrix<Real> & Nx1p = *shape_Nx1p; const Matrix<Real> & Nx2p = *shape_Nx2p; const Matrix<Real> & Nx3p = *shape_Nx3p; const Matrix<Real> & Ny1p = *shape_Ny1p; const Matrix<Real> & Ny2p = *shape_Ny2p; const Matrix<Real> & Ny3p = *shape_Ny3p; B(0, 0) = Np(0, 0); B(0, 6) = Np(0, 1); B(0, 12) = Np(0, 2); B(1, 1) = Np(1, 0); B(1, 7) = Np(1, 1); B(1, 13) = Np(1, 2); B(2, 0) = Np(1, 0); B(2, 1) = Np(0, 0); B(2, 6) = Np(1, 1); B(2, 7) = Np(0, 1); B(2, 12) = Np(1, 2); B(2, 13) = Np(0, 2); B(3, 2) = Nx1p(0, 0); B(3, 3) = Nx2p(0, 0); B(3, 4) = Nx3p(0, 0); B(3, 8) = Nx1p(0, 1); B(3, 9) = Nx2p(0, 1); B(3, 10) = Nx3p(0, 1); B(3, 14) = Nx1p(0, 2); B(3, 15) = Nx2p(0, 2); B(3, 16) = Nx3p(0, 2); B(4, 2) = Ny1p(1, 0); B(4, 3) = Ny2p(1, 0); B(4, 4) = Ny3p(1, 0); B(4, 8) = Ny1p(1, 1); B(4, 9) = Ny2p(1, 1); B(4, 10) = Ny3p(1, 1); B(4, 14) = Ny1p(1, 2); B(4, 15) = Ny2p(1, 2); B(4, 16) = Ny3p(1, 2); B(5, 2) = Nx1p(1, 0) + Ny1p(0, 0); B(5, 3) = Nx2p(1, 0) + Ny2p(0, 0); B(5, 4) = Nx3p(1, 0) + Ny3p(0, 0); B(5, 8) = Nx1p(1, 1) + Ny1p(0, 1); B(5, 9) = Nx2p(1, 1) + Ny2p(0, 1); B(5, 10) = Nx3p(1, 1) + Ny3p(0, 1); B(5, 14) = Nx1p(1, 2) + Ny1p(0, 2); B(5, 15) = Nx2p(1, 2) + Ny2p(0, 2); B(5, 16) = Nx3p(1, 2) + Ny3p(0, 2); ++B_it; ++shape_Np; ++shape_Nx1p; ++shape_Nx2p; ++shape_Nx3p; ++shape_Ny1p; ++shape_Ny2p; ++shape_Ny3p; } } } /* -------------------------------------------------------------------------- */ dumper::Field * StructuralMechanicsModel::createNodalFieldBool(const std::string & field_name, const std::string & group_name, __attribute__((unused)) bool padding_flag) { std::map<std::string, Array<bool> *> uint_nodal_fields; uint_nodal_fields["blocked_dofs"] = blocked_dofs; dumper::Field * field = NULL; field = mesh.createNodalField(uint_nodal_fields[field_name], group_name); return field; } /* -------------------------------------------------------------------------- */ dumper::Field * StructuralMechanicsModel::createNodalFieldReal(const std::string & field_name, const std::string & group_name, bool padding_flag) { UInt n; if (spatial_dimension == 2) { n = 2; } else n = 3; dumper::Field * field = NULL; if (field_name == "displacement") { field = mesh.createStridedNodalField(displacement_rotation, group_name, n, 0, padding_flag); } if (field_name == "rotation") { field = mesh.createStridedNodalField(displacement_rotation, group_name, nb_degree_of_freedom - n, n, padding_flag); } if (field_name == "force") { field = mesh.createStridedNodalField(force_momentum, group_name, n, 0, padding_flag); } if (field_name == "momentum") { field = mesh.createStridedNodalField( force_momentum, group_name, nb_degree_of_freedom - n, n, padding_flag); } if (field_name == "residual") { field = mesh.createNodalField(residual, group_name, padding_flag); } return field; } /* -------------------------------------------------------------------------- */ dumper::Field * StructuralMechanicsModel::createElementalField( const std::string & field_name, const std::string & group_name, __attribute__((unused)) bool padding_flag, const ElementKind & kind, __attribute__((unused)) const std::string & fe_engine_id) { dumper::Field * field = NULL; if (field_name == "element_index_by_material") field = mesh.createElementalField<UInt, Vector, dumper::ElementalField>( field_name, group_name, this->spatial_dimension, kind); return field; } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/structural_mechanics/structural_mechanics_model.hh b/src/model/structural_mechanics/structural_mechanics_model.hh index 87a3f298b..f884e79dd 100644 --- a/src/model/structural_mechanics/structural_mechanics_model.hh +++ b/src/model/structural_mechanics/structural_mechanics_model.hh @@ -1,392 +1,392 @@ /** * @file structural_mechanics_model.hh * * @author Fabian Barras <fabian.barras@epfl.ch> * @author Sébastien Hartmann <sebastien.hartmann@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Damien Spielmann <damien.spielmann@epfl.ch> * * @date creation: Fri Jul 15 2011 * @date last modification: Thu Jan 21 2016 * * @brief Particular implementation of the structural elements in the * StructuralMechanicsModel * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_STRUCTURAL_MECHANICS_MODEL_HH__ #define __AKANTU_STRUCTURAL_MECHANICS_MODEL_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "model.hh" #include "integrator_gauss.hh" #include "shape_linked.hh" #include "aka_types.hh" #include "dumpable.hh" #include "solver.hh" #include "integration_scheme_2nd_order.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class SparseMatrix; } -__BEGIN_AKANTU__ +namespace akantu { struct StructuralMaterial { Real E; Real A; Real I; Real Iz; Real Iy; Real GJ; Real rho; Real t; Real nu; }; struct StructuralMechanicsModelOptions : public ModelOptions { StructuralMechanicsModelOptions(AnalysisMethod analysis_method = _static) : analysis_method(analysis_method) {} AnalysisMethod analysis_method; }; extern const StructuralMechanicsModelOptions default_structural_mechanics_model_options; class StructuralMechanicsModel : public Model { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef FEEngineTemplate<IntegratorGauss, ShapeLinked, _ek_structural> MyFEEngineType; StructuralMechanicsModel(Mesh & mesh, UInt spatial_dimension = _all_dimensions, const ID & id = "structural_mechanics_model", const MemoryID & memory_id = 0); virtual ~StructuralMechanicsModel(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize fully the model void initFull(const ModelOptions & options = default_structural_mechanics_model_options); /// initialize the internal vectors void initArrays(); /// initialize the model void initModel(); /// initialize the solver void initSolver(SolverOptions & options = _solver_no_options); /// initialize the stuff for the implicit solver void initImplicit(bool dynamic = false, SolverOptions & solver_options = _solver_no_options); /// compute the stresses per elements void computeStresses(); /// assemble the stiffness matrix void assembleStiffnessMatrix(); /// assemble the mass matrix for consistent mass resolutions void assembleMass(); /// implicit time integration predictor void implicitPred(); /// implicit time integration corrector void implicitCorr(); /// update the residual vector void updateResidual(); /// solve the system void solve(); bool testConvergenceIncrement(Real tolerance); bool testConvergenceIncrement(Real tolerance, Real & error); void computeRotationMatrix(const ElementType & type); protected: UInt getTangentStiffnessVoigtSize(const ElementType & type); /// compute Rotation Matrices template <const ElementType type> void computeRotationMatrix(__attribute__((unused)) Array<Real> & rotations) {} /// compute A and solve @f[ A\delta u = f_ext - f_int @f] template <NewmarkBeta::IntegrationSchemeCorrectorType type> void solve(Array<Real> & increment, __attribute__((unused)) Real block_val = 1.); /* ------------------------------------------------------------------------ */ /* Mass (structural_mechanics_model_mass.cc) */ /* ------------------------------------------------------------------------ */ /// assemble the mass matrix for either _ghost or _not_ghost elements void assembleMass(GhostType ghost_type); /// computes rho void computeRho(Array<Real> & rho, ElementType type, GhostType ghost_type); /// finish the computation of residual to solve in increment void updateResidualInternal(); /* ------------------------------------------------------------------------ */ private: template <ElementType type> inline UInt getTangentStiffnessVoigtSize(); template <ElementType type> void assembleStiffnessMatrix(); template <ElementType type> void assembleMass(); template <ElementType type> void computeStressOnQuad(); template <ElementType type> void computeTangentModuli(Array<Real> & tangent_moduli); template <ElementType type> void transferBMatrixToSymVoigtBMatrix(Array<Real> & B, bool local = false); template <ElementType type> void transferNMatrixToSymVoigtNMatrix(Array<Real> & N_matrix); /* ------------------------------------------------------------------------ */ /* Dumpable interface */ /* ------------------------------------------------------------------------ */ public: virtual dumper::Field * createNodalFieldReal(const std::string & field_name, const std::string & group_name, bool padding_flag); virtual dumper::Field * createNodalFieldBool(const std::string & field_name, const std::string & group_name, bool padding_flag); virtual dumper::Field * createElementalField(const std::string & field_name, const std::string & group_name, bool padding_flag, const ElementKind & kind, const std::string & fe_engine_id = ""); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// set the value of the time step void setTimeStep(Real time_step); /// return the dimension of the system space AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt); /// get the StructuralMechanicsModel::displacement vector AKANTU_GET_MACRO(Displacement, *displacement_rotation, Array<Real> &); /// get the StructuralMechanicsModel::velocity vector AKANTU_GET_MACRO(Velocity, *velocity, Array<Real> &); /// get the StructuralMechanicsModel::acceleration vector, updated /// by /// StructuralMechanicsModel::updateAcceleration AKANTU_GET_MACRO(Acceleration, *acceleration, Array<Real> &); /// get the StructuralMechanicsModel::force vector (boundary forces) AKANTU_GET_MACRO(Force, *force_momentum, Array<Real> &); /// get the StructuralMechanicsModel::residual vector, computed by /// StructuralMechanicsModel::updateResidual AKANTU_GET_MACRO(Residual, *residual, const Array<Real> &); /// get the StructuralMechanicsModel::boundary vector AKANTU_GET_MACRO(BlockedDOFs, *blocked_dofs, Array<bool> &); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(RotationMatrix, rotation_matrix, Real); AKANTU_GET_MACRO(StiffnessMatrix, *stiffness_matrix, const SparseMatrix &); AKANTU_GET_MACRO(MassMatrix, *mass_matrix, const SparseMatrix &); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Stress, stress, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ElementMaterial, element_material, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Set_ID, set_ID, UInt); void addMaterial(StructuralMaterial & material) { materials.push_back(material); } /** * @brief set the StructuralMechanicsModel::increment_flag to on, the * activate the * update of the StructuralMechanicsModel::increment vector */ void setIncrementFlagOn(); /* ------------------------------------------------------------------------ */ /* Boundaries (structural_mechanics_model_boundary.cc) */ /* ------------------------------------------------------------------------ */ public: /// Compute Linear load function set in global axis template <ElementType type> void computeForcesByGlobalTractionArray(const Array<Real> & tractions); /// Compute Linear load function set in local axis template <ElementType type> void computeForcesByLocalTractionArray(const Array<Real> & tractions); /// compute force vector from a function(x,y,momentum) that describe stresses template <ElementType type> void computeForcesFromFunction(BoundaryFunction in_function, BoundaryFunctionType function_type); /** * solve a step (predictor + convergence loop + corrector) using the * the given convergence method (see akantu::SolveConvergenceMethod) * and the given convergence criteria (see * akantu::SolveConvergenceCriteria) **/ template <SolveConvergenceMethod method, SolveConvergenceCriteria criteria> bool solveStep(Real tolerance, UInt max_iteration = 100); template <SolveConvergenceMethod method, SolveConvergenceCriteria criteria> bool solveStep(Real tolerance, Real & error, UInt max_iteration = 100); /// test if the system is converged template <SolveConvergenceCriteria criteria> bool testConvergence(Real tolerance, Real & error); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// time step Real time_step; /// conversion coefficient form force/mass to acceleration Real f_m2a; /// displacements array Array<Real> * displacement_rotation; /// displacements array at the previous time step (used in finite deformation) Array<Real> * previous_displacement; /// velocities array Array<Real> * velocity; /// accelerations array Array<Real> * acceleration; /// forces array Array<Real> * force_momentum; /// lumped mass array Array<Real> * mass; /// stress arraz ElementTypeMapArray<Real> stress; /// residuals array Array<Real> * residual; /// boundaries array Array<bool> * blocked_dofs; /// position of a dof in the K matrix Array<Int> * equation_number; ElementTypeMapArray<UInt> element_material; // Define sets of beams ElementTypeMapArray<UInt> set_ID; /// local equation_number to global unordered_map<UInt, UInt>::type local_eq_num_to_global; /// stiffness matrix SparseMatrix * stiffness_matrix; /// mass matrix SparseMatrix * mass_matrix; /// velocity damping matrix SparseMatrix * velocity_damping_matrix; /// jacobian matrix SparseMatrix * jacobian_matrix; /// increment of displacement Array<Real> * increment; /// solver for implicit Solver * solver; /// number of degre of freedom UInt nb_degree_of_freedom; // Rotation matrix ElementTypeMapArray<Real> rotation_matrix; /// analysis method check the list in akantu::AnalysisMethod AnalysisMethod method; /// flag defining if the increment must be computed or not bool increment_flag; /// integration scheme of second order used IntegrationScheme2ndOrder * integrator; /* -------------------------------------------------------------------------- */ std::vector<StructuralMaterial> materials; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "structural_mechanics_model_inline_impl.cc" /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const StructuralMechanicsModel & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_STRUCTURAL_MECHANICS_MODEL_HH__ */ diff --git a/src/model/structural_mechanics/structural_mechanics_model_boundary.cc b/src/model/structural_mechanics/structural_mechanics_model_boundary.cc index f26c941b0..3b694b7d3 100644 --- a/src/model/structural_mechanics/structural_mechanics_model_boundary.cc +++ b/src/model/structural_mechanics/structural_mechanics_model_boundary.cc @@ -1,222 +1,222 @@ /** * @file structural_mechanics_model_boundary.cc * * @author Fabian Barras <fabian.barras@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Damien Spielmann <damien.spielmann@epfl.ch> * * @date creation: Fri Jul 15 2011 * @date last modification: Sun Oct 19 2014 * * @brief Implementation of the boundary conditions for StructuralMechanicsModel * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "model.hh" #include "structural_mechanics_model.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template<> void StructuralMechanicsModel::transferNMatrixToSymVoigtNMatrix<_bernoulli_beam_2>(Array<Real> & N_matrix) { AKANTU_DEBUG_IN(); MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>(); UInt nb_nodes_per_element = getFEEngine().getMesh().getNbNodesPerElement(_bernoulli_beam_2); Array<Real>::const_vector_iterator shape_N0 = fem.getShapeFunctions().getShapes(_bernoulli_beam_2, _not_ghost, 0).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_M0 = fem.getShapeFunctions().getShapes(_bernoulli_beam_2, _not_ghost, 1).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_L0 = fem.getShapeFunctions().getShapes(_bernoulli_beam_2, _not_ghost, 2).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Mp = fem.getShapeFunctions().getShapes(_bernoulli_beam_2, _not_ghost, 3).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Lp = fem.getShapeFunctions().getShapes(_bernoulli_beam_2, _not_ghost, 4).begin(nb_nodes_per_element); N_matrix.clear(); Array<Real>::matrix_iterator N_it = N_matrix.begin(nb_degree_of_freedom, nb_degree_of_freedom * nb_nodes_per_element); Array<Real>::matrix_iterator N_end = N_matrix.end(nb_degree_of_freedom, nb_degree_of_freedom * nb_nodes_per_element); for (;N_it != N_end; ++N_it, ++shape_N0, ++shape_M0, ++shape_L0, ++shape_Mp, ++shape_Lp) { Matrix<Real> & N = *N_it; const Vector<Real> & N0 = *shape_N0; const Vector<Real> & M0 = *shape_M0; const Vector<Real> & L0 = *shape_L0; const Vector<Real> & Mp = *shape_Mp; const Vector<Real> & Lp = *shape_Lp; N(0,0) = N0(0); N(0,3) = N0(1); N(1,1) = M0(0); N(1,2) = L0(0); N(1,4) = M0(1); N(1,5) = L0(1); N(2,1) = Mp(0); N(2,2) = Lp(0); N(2,4) = Mp(1); N(2,5) = Lp(1); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<> void StructuralMechanicsModel::transferNMatrixToSymVoigtNMatrix<_bernoulli_beam_3>(Array<Real> & N_matrix) { AKANTU_DEBUG_IN(); ElementType type = _bernoulli_beam_3; MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>(); UInt nb_nodes_per_element = getFEEngine().getMesh().getNbNodesPerElement(type); Array<Real>::const_vector_iterator shape_N0 = fem.getShapeFunctions().getShapes(type, _not_ghost, 0).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_M0 = fem.getShapeFunctions().getShapes(type, _not_ghost, 1).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_L0 = fem.getShapeFunctions().getShapes(type, _not_ghost, 2).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Mp = fem.getShapeFunctions().getShapes(type, _not_ghost, 3).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Lp = fem.getShapeFunctions().getShapes(type, _not_ghost, 4).begin(nb_nodes_per_element); N_matrix.clear(); Array<Real>::matrix_iterator N_it = N_matrix.begin(nb_degree_of_freedom, nb_degree_of_freedom * nb_nodes_per_element); Array<Real>::matrix_iterator N_end = N_matrix.end(nb_degree_of_freedom, nb_degree_of_freedom * nb_nodes_per_element); for (; N_it != N_end; ++N_it, ++shape_N0, ++shape_M0, ++shape_L0, ++shape_Mp, ++shape_Lp) { Matrix<Real> & N = *N_it; const Vector<Real> & N0 = *shape_N0; const Vector<Real> & M0 = *shape_M0; const Vector<Real> & L0 = *shape_L0; const Vector<Real> & Mp = *shape_Mp; const Vector<Real> & Lp = *shape_Lp; N(0,0) = N0(0); N(0,6) = N0(1); N(1,1) = M0(0); N(1,5) = L0(0); N(1,7) = M0(1); N(1,11) = L0(1); N(2,2) = M0(0); N(2,4) = -L0(0); N(2,8) = M0(1); N(2,10) = -L0(1); N(3,3) = N0(0); N(3,9) = N0(1); N(4,2) = Mp(0); N(4,4) = -Lp(0); N(4,8) = Mp(1); N(4,10) = -Lp(1); N(5,1) = Mp(0); N(5,5) = Lp(0); N(5,7) = Mp(1); N(5,11) = Lp(1); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<> void StructuralMechanicsModel::transferNMatrixToSymVoigtNMatrix<_kirchhoff_shell>(Array<Real> & N_matrix) { AKANTU_DEBUG_IN(); ElementType type = _kirchhoff_shell; MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>(); UInt nb_nodes_per_element = getFEEngine().getMesh().getNbNodesPerElement(type); Array<Real>::const_vector_iterator shape_N0 = fem.getShapeFunctions().getShapes(type, _not_ghost, 0).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Nw2 = fem.getShapeFunctions().getShapes(type, _not_ghost, 1).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Nw3 = fem.getShapeFunctions().getShapes(type, _not_ghost, 2).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Nx1 = fem.getShapeFunctions().getShapes(type, _not_ghost, 3).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Nx2 = fem.getShapeFunctions().getShapes(type, _not_ghost, 4).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Nx3 = fem.getShapeFunctions().getShapes(type, _not_ghost, 5).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Ny1 = fem.getShapeFunctions().getShapes(type, _not_ghost, 6).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Ny2 = fem.getShapeFunctions().getShapes(type, _not_ghost, 7).begin(nb_nodes_per_element); Array<Real>::const_vector_iterator shape_Ny3 = fem.getShapeFunctions().getShapes(type, _not_ghost, 8).begin(nb_nodes_per_element); N_matrix.clear(); Array<Real>::matrix_iterator N_it = N_matrix.begin(nb_degree_of_freedom, nb_degree_of_freedom * nb_nodes_per_element); Array<Real>::matrix_iterator N_end = N_matrix.end(nb_degree_of_freedom, nb_degree_of_freedom * nb_nodes_per_element); for (; N_it != N_end; ++N_it, ++shape_N0, ++shape_Nw2, ++shape_Nw3, ++shape_Nx1, ++shape_Nx2, ++shape_Nx3, ++shape_Ny1, ++shape_Ny2, ++shape_Ny3) { Matrix<Real> & N = *N_it; const Vector<Real> & N0 = *shape_N0; const Vector<Real> & Nw2 = *shape_Nw2; const Vector<Real> & Nw3 = *shape_Nw3; const Vector<Real> & Nx1 = *shape_Nx1; const Vector<Real> & Nx2 = *shape_Nx2; const Vector<Real> & Nx3 = *shape_Nx3; const Vector<Real> & Ny1 = *shape_Ny1; const Vector<Real> & Ny2 = *shape_Ny2; const Vector<Real> & Ny3 = *shape_Ny3; N(0,0) = N0(0); N(0,5) = N0(1); N(0,10) = N0(2); N(1,1) = N0(0); N(1,5) = N0(1); N(1,11) = N0(2); N(2,2) = N0(0); N(2,3) = Nw2(0); N(2,4) = Nw3(0); N(2,7) = N0(1); N(2,8) = Nw2(1); N(2,9) = Nw3(1); N(2,12) = N0(2); N(2,13) = Nw2(2); N(2,14) = Nw3(2); N(3,2) = Nx1(0); N(3,3) = Nx2(0); N(3,4) = Nx3(0); N(3,7) = Nx1(1); N(3,8) = Nx2(1); N(3,9) = Nx3(1); N(3,12) = Nx1(2); N(3,13) = Nx2(2); N(3,14) = Nx3(2); N(4,2) = Ny1(0); N(4,3) = Ny2(0); N(4,4) = Ny3(0); N(4,7) = Ny1(1); N(4,8) = Ny2(1); N(4,9) = Ny3(1); N(4,12) = Ny1(2); N(4,13) = Ny2(2); N(4,14) = Ny3(2); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/structural_mechanics/structural_mechanics_model_mass.cc b/src/model/structural_mechanics/structural_mechanics_model_mass.cc index f9643aabc..d7bbc6811 100644 --- a/src/model/structural_mechanics/structural_mechanics_model_mass.cc +++ b/src/model/structural_mechanics/structural_mechanics_model_mass.cc @@ -1,100 +1,100 @@ /** * @file structural_mechanics_model_mass.cc * * @author Sébastien Hartmann <sebastien.hartmann@epfl.ch> * * @date creation: Mon Jul 07 2014 * @date last modification: Thu Oct 15 2015 * * @brief function handling mass computation * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "structural_mechanics_model.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::assembleMass(){ AKANTU_DEBUG_IN(); if(!mass_matrix){ std::stringstream sstr; sstr << id << ":mass_matrix"; mass_matrix = new SparseMatrix(*jacobian_matrix, sstr.str(), memory_id); } assembleMass(_not_ghost); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::assembleMass(GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real> rho_1(0,1); mass_matrix->clear(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_structural); Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type, _ek_structural); for(; it != end; ++it){ ElementType type = *it; #define ASSEMBLE_MASS(type) \ assembleMass<type>(); AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(ASSEMBLE_MASS); #undef ASSEMBLE_MASS } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::computeRho(Array<Real> & rho, ElementType type, GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt nb_element = getFEEngine().getMesh().getNbElement(type); UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(type); Array<UInt> & el_mat = element_material(type, ghost_type); for (UInt e = 0; e < nb_element; ++e){ UInt mat = el_mat(e); Real rho_el = materials[mat].rho; for (UInt q = e*nb_quadrature_points; q < e*nb_quadrature_points + nb_quadrature_points; ++q){ rho(q) = rho_el; } } AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu diff --git a/src/model/time_step_solver.hh b/src/model/time_step_solver.hh index ebb306fbd..03c822aa8 100644 --- a/src/model/time_step_solver.hh +++ b/src/model/time_step_solver.hh @@ -1,121 +1,121 @@ /** * @file time_step_solver.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Mon Aug 24 12:42:04 2015 * * @brief This corresponding to the time step evolution solver * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" #include "aka_memory.hh" #include "integration_scheme.hh" #include "parameter_registry.hh" #include "solver_callback.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_TIME_STEP_SOLVER_HH__ #define __AKANTU_TIME_STEP_SOLVER_HH__ namespace akantu { class DOFManager; class NonLinearSolver; } -__BEGIN_AKANTU__ +namespace akantu { class TimeStepSolver : public Memory, public ParameterRegistry, public SolverCallback { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: TimeStepSolver(DOFManager & dof_manager, const TimeStepSolverType & type, NonLinearSolver & non_linear_solver, const ID & id, UInt memory_id); virtual ~TimeStepSolver(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// solves on step virtual void solveStep(SolverCallback & solver_callback) = 0; /// register an integration scheme for a given dof virtual void setIntegrationScheme(const ID & dof_id, const IntegrationSchemeType & type, IntegrationScheme::SolutionType solution_type = IntegrationScheme::_not_defined) = 0; /// replies if a integration scheme has been set virtual bool hasIntegrationScheme(const ID & dof_id) const = 0; /* ------------------------------------------------------------------------ */ /* Solver Callback interface */ /* ------------------------------------------------------------------------ */ public: /// implementation of the SolverCallback::predictor() virtual void predictor(); /// implementation of the SolverCallback::corrector() virtual void corrector(); /// implementation of the SolverCallback::assembleJacobian() virtual void assembleJacobian(); /// implementation of the SolverCallback::assembleResidual() virtual void assembleResidual(); /* ------------------------------------------------------------------------ */ /* Accessor */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(TimeStep, time_step, Real); AKANTU_SET_MACRO(TimeStep, time_step, Real); AKANTU_GET_MACRO(NonLinearSolver, non_linear_solver, const NonLinearSolver &); AKANTU_GET_MACRO_NOT_CONST(NonLinearSolver, non_linear_solver, NonLinearSolver &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Underlying dof manager containing the dof to treat DOFManager & _dof_manager; /// Type of solver TimeStepSolverType type; /// The time step for this solver Real time_step; /// Temporary storage for solver callback SolverCallback * solver_callback; /// NonLinearSolver used by this tome step solver NonLinearSolver & non_linear_solver; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_TIME_STEP_SOLVER_HH__ */ diff --git a/src/model/time_step_solvers/time_step_solver.cc b/src/model/time_step_solvers/time_step_solver.cc index 4df58122a..934d68af2 100644 --- a/src/model/time_step_solvers/time_step_solver.cc +++ b/src/model/time_step_solvers/time_step_solver.cc @@ -1,93 +1,93 @@ /** * @file time_step_solver.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Mon Oct 12 16:56:43 2015 * * @brief Implementation of common part of TimeStepSolvers * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "time_step_solver.hh" #include "non_linear_solver.hh" #include "dof_manager.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ TimeStepSolver::TimeStepSolver(DOFManager & dof_manager, const TimeStepSolverType & type, NonLinearSolver & non_linear_solver, const ID & id, UInt memory_id) : Memory(id, memory_id), SolverCallback(dof_manager), _dof_manager(dof_manager), type(type), time_step(0.), solver_callback(NULL), non_linear_solver(non_linear_solver) { this->registerSubRegistry("non_linear_solver", non_linear_solver); } /* -------------------------------------------------------------------------- */ TimeStepSolver::~TimeStepSolver() {} /* -------------------------------------------------------------------------- */ void TimeStepSolver::predictor() { AKANTU_DEBUG_ASSERT( this->solver_callback != NULL, "This function cannot be called if the solver_callback is not set"); this->solver_callback->predictor(); } /* -------------------------------------------------------------------------- */ void TimeStepSolver::corrector() { AKANTU_DEBUG_ASSERT( this->solver_callback != NULL, "This function cannot be called if the solver_callback is not set"); this->solver_callback->corrector(); } /* -------------------------------------------------------------------------- */ void TimeStepSolver::assembleJacobian() { AKANTU_DEBUG_ASSERT( this->solver_callback != NULL, "This function cannot be called if the solver_callback is not set"); // this->_dof_manager.clearMatrix("J"); this->solver_callback->assembleJacobian(); } /* -------------------------------------------------------------------------- */ void TimeStepSolver::assembleResidual() { AKANTU_DEBUG_ASSERT( this->solver_callback != NULL, "This function cannot be called if the solver_callback is not set"); this->_dof_manager.clearResidual(); this->solver_callback->assembleResidual(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/time_step_solvers/time_step_solver_default.cc b/src/model/time_step_solvers/time_step_solver_default.cc index 7655c1b8c..327d2fa07 100644 --- a/src/model/time_step_solvers/time_step_solver_default.cc +++ b/src/model/time_step_solvers/time_step_solver_default.cc @@ -1,273 +1,273 @@ /** * @file time_step_solver_default.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Wed Sep 16 10:20:55 2015 * * @brief Default implementation of the time step solver * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "time_step_solver_default.hh" #include "dof_manager_default.hh" #include "integration_scheme_1st_order.hh" #include "integration_scheme_2nd_order.hh" #include "mesh.hh" #include "non_linear_solver.hh" #include "pseudo_time.hh" #include "sparse_matrix_aij.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ TimeStepSolverDefault::TimeStepSolverDefault( DOFManagerDefault & dof_manager, const TimeStepSolverType & type, NonLinearSolver & non_linear_solver, const ID & id, UInt memory_id) : TimeStepSolver(dof_manager, type, non_linear_solver, id, memory_id), dof_manager(dof_manager), is_mass_lumped(false) { switch (type) { case _tsst_dynamic: break; case _tsst_dynamic_lumped: this->is_mass_lumped = true; break; case _tsst_static: /// initialize a static time solver for callback dofs break; } } /* -------------------------------------------------------------------------- */ void TimeStepSolverDefault::setIntegrationScheme( const ID & dof_id, const IntegrationSchemeType & type, IntegrationScheme::SolutionType solution_type) { if (this->integration_schemes.find(dof_id) != this->integration_schemes.end()) { AKANTU_EXCEPTION("Their DOFs " << dof_id << " have already an integration scheme associated"); } IntegrationScheme * integration_scheme = NULL; if (this->is_mass_lumped) { switch (type) { case _ist_forward_euler: { integration_scheme = new ForwardEuler(dof_manager, dof_id); break; } case _ist_central_difference: { integration_scheme = new CentralDifference(dof_manager, dof_id); break; } default: AKANTU_EXCEPTION( "This integration scheme cannot be used in lumped dynamic"); } } else { switch (type) { case _ist_pseudo_time: { integration_scheme = new PseudoTime(dof_manager, dof_id); break; } case _ist_forward_euler: { integration_scheme = new ForwardEuler(dof_manager, dof_id); break; } case _ist_trapezoidal_rule_1: { integration_scheme = new TrapezoidalRule1(dof_manager, dof_id); break; } case _ist_backward_euler: { integration_scheme = new BackwardEuler(dof_manager, dof_id); break; } case _ist_central_difference: { integration_scheme = new CentralDifference(dof_manager, dof_id); break; } case _ist_fox_goodwin: { integration_scheme = new FoxGoodwin(dof_manager, dof_id); break; } case _ist_trapezoidal_rule_2: { integration_scheme = new TrapezoidalRule2(dof_manager, dof_id); break; } case _ist_linear_acceleration: { integration_scheme = new LinearAceleration(dof_manager, dof_id); break; } case _ist_generalized_trapezoidal: { integration_scheme = new GeneralizedTrapezoidal(dof_manager, dof_id); break; } case _ist_newmark_beta: integration_scheme = new NewmarkBeta(dof_manager, dof_id); break; } } AKANTU_DEBUG_ASSERT(integration_scheme != nullptr, "No integration scheme was found for the provided types"); this->integration_schemes[dof_id] = integration_scheme; this->solution_types[dof_id] = solution_type; this->integration_schemes_owner.insert(dof_id); } /* -------------------------------------------------------------------------- */ bool TimeStepSolverDefault::hasIntegrationScheme(const ID & dof_id) const { return this->integration_schemes.find(dof_id) != this->integration_schemes.end(); } /* -------------------------------------------------------------------------- */ TimeStepSolverDefault::~TimeStepSolverDefault() { DOFsIntegrationSchemesOwner::iterator it = this->integration_schemes_owner.begin(); DOFsIntegrationSchemesOwner::iterator end = this->integration_schemes_owner.end(); for (; it != end; ++it) { delete this->integration_schemes[*it]; } this->integration_schemes.clear(); } /* -------------------------------------------------------------------------- */ void TimeStepSolverDefault::solveStep(SolverCallback & solver_callback) { this->solver_callback = &solver_callback; this->non_linear_solver.solve(*this); this->solver_callback = NULL; } /* -------------------------------------------------------------------------- */ void TimeStepSolverDefault::predictor() { AKANTU_DEBUG_IN(); TimeStepSolver::predictor(); IntegrationScheme * integration_scheme; ID dof_id; for(auto & pair : this->integration_schemes) { std::tie(dof_id, integration_scheme) = pair; if (this->dof_manager.hasPreviousDOFs(dof_id)) { this->dof_manager.savePreviousDOFs(dof_id); } /// integrator predictor integration_scheme->predictor(this->time_step); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void TimeStepSolverDefault::corrector() { AKANTU_DEBUG_IN(); TimeStepSolver::corrector(); IntegrationScheme * integration_scheme; ID dof_id; for(auto & pair : this->integration_schemes) { std::tie(dof_id, integration_scheme) = pair; const auto & solution_type = this->solution_types[dof_id]; integration_scheme->corrector(solution_type, this->time_step); /// computing the increment of dof if needed if (this->dof_manager.hasDOFsIncrement(dof_id)) { if (!this->dof_manager.hasPreviousDOFs(dof_id)) { AKANTU_DEBUG_WARNING("In order to compute the increment of " << dof_id << " a 'previous' has to be registered"); continue; } Array<Real> & increment = this->dof_manager.getDOFsIncrement(dof_id); Array<Real> & previous = this->dof_manager.getPreviousDOFs(dof_id); UInt dof_array_comp = this->dof_manager.getDOFs(dof_id).getNbComponent(); auto prev_dof_it = previous.begin(dof_array_comp); auto incr_it = increment.begin(dof_array_comp); auto incr_end = increment.end(dof_array_comp); increment.copy(this->dof_manager.getDOFs(dof_id)); for (; incr_it != incr_end; ++incr_it, ++prev_dof_it) { *incr_it -= *prev_dof_it; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void TimeStepSolverDefault::assembleJacobian() { AKANTU_DEBUG_IN(); TimeStepSolver::assembleJacobian(); IntegrationScheme * integration_scheme; ID dof_id; for(auto & pair : this->integration_schemes) { std::tie(dof_id, integration_scheme) = pair; const auto & solution_type = this->solution_types[dof_id]; integration_scheme->assembleJacobian(solution_type, this->time_step); } this->dof_manager.applyBoundary("J"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void TimeStepSolverDefault::assembleResidual() { AKANTU_DEBUG_IN(); TimeStepSolver::assembleResidual(); IntegrationScheme * integration_scheme; ID dof_id; for(auto & pair : this->integration_schemes) { std::tie(dof_id, integration_scheme) = pair; integration_scheme->assembleResidual(this->is_mass_lumped); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/model/time_step_solvers/time_step_solver_default.hh b/src/model/time_step_solvers/time_step_solver_default.hh index 27ebbec39..5c9e57e83 100644 --- a/src/model/time_step_solvers/time_step_solver_default.hh +++ b/src/model/time_step_solvers/time_step_solver_default.hh @@ -1,110 +1,110 @@ /** * @file time_step_solver_default.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Mon Aug 24 17:10:29 2015 * * @brief Default implementation for the time stepper * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "time_step_solver.hh" #include "integration_scheme.hh" /* -------------------------------------------------------------------------- */ #include <map> #include <set> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_TIME_STEP_SOLVER_DEFAULT_HH__ #define __AKANTU_TIME_STEP_SOLVER_DEFAULT_HH__ namespace akantu { class DOFManagerDefault; } -__BEGIN_AKANTU__ +namespace akantu { class TimeStepSolverDefault : public TimeStepSolver { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: TimeStepSolverDefault(DOFManagerDefault & dof_manager, const TimeStepSolverType & type, NonLinearSolver & non_linear_solver, const ID & id, UInt memory_id); virtual ~TimeStepSolverDefault(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// registers an integration scheme for a given dof void setIntegrationScheme(const ID & dof_id, const IntegrationSchemeType & type, IntegrationScheme::SolutionType solution_type = IntegrationScheme::_not_defined); virtual bool hasIntegrationScheme(const ID & dof_id) const; /// implementation of the TimeStepSolver::predictor() virtual void predictor(); /// implementation of the TimeStepSolver::corrector() virtual void corrector(); /// implementation of the TimeStepSolver::assembleJacobian() virtual void assembleJacobian(); /// implementation of the TimeStepSolver::assembleResidual() virtual void assembleResidual(); /// implementation of the generic TimeStepSolver::solveStep() virtual void solveStep(SolverCallback & solver_callback); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: typedef std::map<ID, IntegrationScheme *> DOFsIntegrationSchemes; typedef std::map<ID, IntegrationScheme::SolutionType> DOFsIntegrationSchemesSolutionTypes; typedef std::set<ID> DOFsIntegrationSchemesOwner; /// DOFManager with its real type DOFManagerDefault & dof_manager; /// Underlying integration scheme per dof, \todo check what happens in dynamic /// in case of coupled equations DOFsIntegrationSchemes integration_schemes; /// defines if the solver is owner of the memory or not DOFsIntegrationSchemesOwner integration_schemes_owner; /// Type of corrector to use DOFsIntegrationSchemesSolutionTypes solution_types; /// define if the mass matrix is lumped or not bool is_mass_lumped; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_TIME_STEP_SOLVER_DEFAULT_HH__ */ diff --git a/src/model/time_step_solvers/time_step_solver_default_explicit.hh b/src/model/time_step_solvers/time_step_solver_default_explicit.hh index 821bf2f6f..cceb0d50d 100644 --- a/src/model/time_step_solvers/time_step_solver_default_explicit.hh +++ b/src/model/time_step_solvers/time_step_solver_default_explicit.hh @@ -1,78 +1,78 @@ /** * @file time_step_solver_default_explicit.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Mon Aug 24 14:21:44 2015 * * @brief Default solver for explicit resolution * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_TIME_STEP_SOLVER_DEFAULT_EXPLICIT_HH__ #define __AKANTU_TIME_STEP_SOLVER_DEFAULT_EXPLICIT_HH__ -__BEGIN_AKANTU__ +namespace akantu { class TimeStepSolverDefaultExplicit : public TimeStepSolverDefault { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: TimeStepSolverDefaultExplicit(); virtual ~TimeStepSolverDefaultExplicit(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void solveStep(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "time_step_solver_default_explicit_inline_impl.cc" /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const TimeStepSolverDefaultExplicit & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_TIME_STEP_SOLVER_DEFAULT_EXPLICIT_HH__ */ diff --git a/src/model/time_step_solvers/time_step_solver_default_solver_callback.hh b/src/model/time_step_solvers/time_step_solver_default_solver_callback.hh index 96fb125a9..2a4cac0f8 100644 --- a/src/model/time_step_solvers/time_step_solver_default_solver_callback.hh +++ b/src/model/time_step_solvers/time_step_solver_default_solver_callback.hh @@ -1,63 +1,63 @@ /** * @file time_step_solver_default_solver_callback.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Mon Sep 28 18:58:07 2015 * * @brief Implementation of the NonLinearSolverCallback for the time step solver * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "non_linear_solver_callback.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_TIME_STEP_SOLVER_DEFAULT_SOLVER_CALLBACK_HH__ #define __AKANTU_TIME_STEP_SOLVER_DEFAULT_SOLVER_CALLBACK_HH__ -__BEGIN_AKANTU__ +namespace akantu { class TimeStepSolverCallback : public NonLinearSolverCallback { /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// callback to assemble the Jacobian Matrix virtual void assembleJacobian(); /// callback to assemble the residual (rhs) virtual void assembleResidual(); /* ------------------------------------------------------------------------ */ /* Dynamic simulations part */ /* ------------------------------------------------------------------------ */ /// callback for the predictor (in case of dynamic simulation) virtual void predictor(); /// callback for the corrector (in case of dynamic simulation) virtual void corrector(); }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_TIME_STEP_SOLVER_DEFAULT_SOLVER_CALLBACK_HH__ */ diff --git a/src/python/python_functor.cc b/src/python/python_functor.cc index edde6ddfe..167ca871b 100644 --- a/src/python/python_functor.cc +++ b/src/python/python_functor.cc @@ -1,80 +1,80 @@ /** * @file python_functor.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Fri Nov 13 2015 * * @brief Python functor interface * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <vector> #include "python_functor.hh" #include "aka_common.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ PythonFunctor::PythonFunctor(PyObject * obj):python_obj(obj){ } /* -------------------------------------------------------------------------- */ PyObject * PythonFunctor::callFunctor(PyObject * functor, PyObject * args, PyObject * kwargs) const{ if (!PyCallable_Check(functor)) AKANTU_EXCEPTION("Provided functor is not a function"); PyObject * pValue = PyObject_Call(functor, args,kwargs); PyObject* exception_type = PyErr_Occurred(); if (exception_type){ PyObject * exception; PyObject * traceback; PyErr_Fetch(&exception_type, &exception, &traceback); PyObject_Print(exception_type, stdout, Py_PRINT_RAW); PyObject_Print(exception, stdout, Py_PRINT_RAW); std::stringstream sstr; sstr << "Exception occured while calling the functor: "; PyObject * exception_mesg = PyObject_GetAttrString(exception,"message"); if (exception_mesg && PyString_Check(exception_mesg)) sstr << PyString_AsString(exception_mesg); else sstr << PyString_AsString(exception); AKANTU_EXCEPTION(sstr.str()); } return pValue; } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/python/python_functor.hh b/src/python/python_functor.hh index 0c55677ac..61977c71b 100644 --- a/src/python/python_functor.hh +++ b/src/python/python_functor.hh @@ -1,134 +1,134 @@ /** * @file python_functor.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Nov 15 2015 * * @brief Python Functor interface * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_PYTHON_FUNCTOR_HH__ #define __AKANTU_PYTHON_FUNCTOR_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include <vector> #include <map> #include <Python.h> #include <vector> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ class PythonFunctor { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: PythonFunctor(PyObject * obj); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ protected: /// call the python functor PyObject * callFunctor(PyObject * functor, PyObject * args, PyObject * kwargs) const; /// call the python functor from variadic types template <typename return_type, typename... Params> return_type callFunctor(const std::string & functor_name, Params &... parameters) const; /// empty function to cose the recursive template loop inline void packArguments(std::vector<PyObject *> & pArgs) const; /// get the python function object inline PyObject * getPythonFunction(const std::string & functor_name) const; /// variadic template for unknown number of arguments to unpack template <typename T, typename... Args> inline void packArguments(std::vector<PyObject *> & pArgs, T & p, Args &... params) const; /// convert an akantu object to python template <typename T> inline PyObject * convertToPython(const T & akantu_obj) const; /// convert a stl vector to python template <typename T> inline PyObject * convertToPython(const std::vector<T> & akantu_obj) const; /// convert a stl vector to python template <typename T> inline PyObject * convertToPython(const std::vector<Array<T> *> & akantu_obj) const; /// convert a stl vector to python template <typename T1, typename T2> inline PyObject * convertToPython(const std::map<T1, T2> & akantu_obj) const; /// convert an akantu vector to python template <typename T> inline PyObject * convertToPython(const Vector<T> & akantu_obj) const; /// convert an akantu vector to python template <typename T> inline PyObject * convertToPython(const Array<T> & akantu_obj) const; /// convert an akantu vector to python template <typename T> inline PyObject * convertToPython(Array<T> * akantu_obj) const; /// convert a akantu matrix to python template <typename T> inline PyObject * convertToPython(const Matrix<T> & akantu_obj) const; /// convert a python object to an akantu object template <typename return_type> inline return_type convertToAkantu(PyObject * python_obj) const; /// convert a python object to an akantu object template <typename T> inline std::vector<T> convertListToAkantu(PyObject * python_obj) const; /// returns the numpy data type code template <typename T> inline int getPythonDataTypeCode() const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ PyObject * python_obj; }; /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu /* -------------------------------------------------------------------------- */ #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include "python_functor_inline_impl.cc" /* -------------------------------------------------------------------------- */ #endif /* __AKANTU_PYTHON_FUNCTOR_HH__ */ diff --git a/src/python/python_functor_inline_impl.cc b/src/python/python_functor_inline_impl.cc index 3e5721229..bd9bba712 100644 --- a/src/python/python_functor_inline_impl.cc +++ b/src/python/python_functor_inline_impl.cc @@ -1,337 +1,337 @@ /** * @file python_functor_inline_impl.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * * @date creation: Fri Nov 13 2015 * @date last modification: Wed Nov 18 2015 * * @brief Python functor interface * * @section LICENSE * * Copyright (©) 2015 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 <http://www.gnu.org/licenses/>. * */ #ifndef __AKANTU_PYTHON_FUNCTOR_INLINE_IMPL_CC__ #define __AKANTU_PYTHON_FUNCTOR_INLINE_IMPL_CC__ /* -------------------------------------------------------------------------- */ #include "integration_point.hh" #include <numpy/arrayobject.h> #include <typeinfo> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <typename T> inline int PythonFunctor::getPythonDataTypeCode() const { AKANTU_EXCEPTION("undefined type: " << debug::demangle(typeid(T).name())); } /* -------------------------------------------------------------------------- */ template <> inline int PythonFunctor::getPythonDataTypeCode<bool>() const { int data_typecode = NPY_NOTYPE; size_t s = sizeof(bool); switch (s) { case 1: data_typecode = NPY_BOOL; break; case 2: data_typecode = NPY_UINT16; break; case 4: data_typecode = NPY_UINT32; break; case 8: data_typecode = NPY_UINT64; break; } return data_typecode; } /* -------------------------------------------------------------------------- */ template <> inline int PythonFunctor::getPythonDataTypeCode<double>() const { return NPY_DOUBLE; } /* -------------------------------------------------------------------------- */ template <typename T> PyObject * PythonFunctor::convertToPython(__attribute__((unused)) const T & akantu_object) const { AKANTU_DEBUG_ERROR( __func__ << " : not implemented yet !" << std::endl << debug::demangle(typeid(T).name()) << "\n*************************************************\n\n\n"); } /* -------------------------------------------------------------------------- */ template <> inline PyObject * PythonFunctor::convertToPython<double>(const double & akantu_object) const { return PyFloat_FromDouble(akantu_object); } /* -------------------------------------------------------------------------- */ template <> inline PyObject * PythonFunctor::convertToPython<UInt>(const UInt & akantu_object) const { return PyInt_FromLong(akantu_object); } /* -------------------------------------------------------------------------- */ template <> inline PyObject * PythonFunctor::convertToPython<bool>(const bool & akantu_object) const { return PyBool_FromLong(long(akantu_object)); } /* -------------------------------------------------------------------------- */ template <typename T> inline PyObject * PythonFunctor::convertToPython(const std::vector<T> & array) const { int data_typecode = getPythonDataTypeCode<T>(); npy_intp dims[1] = {int(array.size())}; PyObject * obj = PyArray_SimpleNewFromData(1, dims, data_typecode, const_cast<T *>(&array[0])); PyArrayObject * res = (PyArrayObject *)obj; return (PyObject *)res; } /* -------------------------------------------------------------------------- */ template <typename T> inline PyObject * PythonFunctor::convertToPython(const std::vector<Array<T> *> & array) const { PyObject * res = PyDict_New(); for (auto a : array) { PyObject * obj = this->convertToPython(*a); PyObject * name = this->convertToPython(a->getID()); PyDict_SetItem(res, name, obj); } return (PyObject *)res; } /* -------------------------------------------------------------------------- */ template <typename T1, typename T2> inline PyObject * PythonFunctor::convertToPython(const std::map<T1, T2> & map) const { PyObject * res = PyDict_New(); for (auto a : map) { PyObject * key = this->convertToPython(a.first); PyObject * value = this->convertToPython(a.second); PyDict_SetItem(res, key, value); } return (PyObject *)res; } /* -------------------------------------------------------------------------- */ template <typename T> PyObject * PythonFunctor::convertToPython(const Vector<T> & array) const { int data_typecode = getPythonDataTypeCode<T>(); npy_intp dims[1] = {array.size()}; PyObject * obj = PyArray_SimpleNewFromData(1, dims, data_typecode, array.storage()); PyArrayObject * res = (PyArrayObject *)obj; return (PyObject *)res; } /* -------------------------------------------------------------------------- */ template <typename T> PyObject * PythonFunctor::convertToPython(const Array<T> & array) const { int data_typecode = getPythonDataTypeCode<T>(); npy_intp dims[2] = {array.getSize(), array.getNbComponent()}; PyObject * obj = PyArray_SimpleNewFromData(2, dims, data_typecode, array.storage()); PyArrayObject * res = (PyArrayObject *)obj; return (PyObject *)res; } /* -------------------------------------------------------------------------- */ template <typename T> PyObject * PythonFunctor::convertToPython(Array<T> * array) const { return this->convertToPython(*array); } /* -------------------------------------------------------------------------- */ template <typename T> PyObject * PythonFunctor::convertToPython(const Matrix<T> & mat) const { int data_typecode = getPythonDataTypeCode<T>(); npy_intp dims[2] = {mat.size(0), mat.size(1)}; PyObject * obj = PyArray_SimpleNewFromData(2, dims, data_typecode, mat.storage()); PyArrayObject * res = (PyArrayObject *)obj; return (PyObject *)res; } /* -------------------------------------------------------------------------- */ template <> inline PyObject * PythonFunctor::convertToPython<std::string>(const std::string & str) const { return PyString_FromString(str.c_str()); } /* -------------------------------------------------------------------------- */ template <> inline PyObject * PythonFunctor::convertToPython<IntegrationPoint>( const IntegrationPoint & qp) const { PyObject * input = PyDict_New(); PyObject * num_point = this->convertToPython(qp.num_point); PyObject * global_num = this->convertToPython(qp.global_num); PyObject * material_id = this->convertToPython(qp.material_id); PyObject * position = this->convertToPython(qp.getPosition()); PyDict_SetItemString(input, "num_point", num_point); PyDict_SetItemString(input, "global_num", global_num); PyDict_SetItemString(input, "material_id", material_id); PyDict_SetItemString(input, "position", position); return input; } /* -------------------------------------------------------------------------- */ inline PyObject * PythonFunctor::getPythonFunction(const std::string & functor_name) const { if (!PyInstance_Check(this->python_obj)) AKANTU_EXCEPTION("Python object is not an instance"); // if (!PyDict_Check(this->python_obj)) // AKANTU_EXCEPTION("Python object is not a dictionary"); // PyObject * keys = PyDict_Keys(dict); // PyObject_Print(keys, stdout, Py_PRINT_RAW); PyObject * pFunctor = PyObject_GetAttrString(this->python_obj, functor_name.c_str()); if (!pFunctor) AKANTU_EXCEPTION("Python dictionary has no " << functor_name << " entry"); return pFunctor; } /* -------------------------------------------------------------------------- */ inline void PythonFunctor::packArguments(__attribute__((unused)) std::vector<PyObject *> & p_args) const {} /* -------------------------------------------------------------------------- */ template <typename T, typename... Args> inline void PythonFunctor::packArguments(std::vector<PyObject *> & p_args, T & p, Args &... params) const { p_args.push_back(this->convertToPython(p)); if (sizeof...(params) != 0) this->packArguments(p_args, params...); } /* -------------------------------------------------------------------------- */ template <typename return_type, typename... Params> return_type PythonFunctor::callFunctor(const std::string & functor_name, Params &... parameters) const { _import_array(); std::vector<PyObject *> arg_vector; this->packArguments(arg_vector, parameters...); PyObject * pArgs = PyTuple_New(arg_vector.size()); for (UInt i = 0; i < arg_vector.size(); ++i) { PyTuple_SetItem(pArgs, i, arg_vector[i]); } PyObject * kwargs = PyDict_New(); PyObject * pFunctor = getPythonFunction(functor_name); PyObject * res = this->callFunctor(pFunctor, pArgs, kwargs); // for (auto a: arg_vector) { // // if (PyDict_Check(a)){ // // PyObject* values = PyDict_Values(a); // // UInt sz = PyList_GET_SIZE(values); // // for (UInt i = 0; i < sz; ++i) { // // Py_XDECREF(PyList_GetItem(values,i)); // // } // // } // // Py_XDECREF(a); // } Py_XDECREF(pArgs); Py_XDECREF(kwargs); return this->convertToAkantu<return_type>(res); } /* -------------------------------------------------------------------------- */ template <typename return_type> inline return_type PythonFunctor::convertToAkantu(PyObject * python_obj) const { if (PyList_Check(python_obj)) { return this->convertListToAkantu<typename return_type::value_type>( python_obj); } AKANTU_DEBUG_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ template <> inline void PythonFunctor::convertToAkantu<void>(PyObject * python_obj) const { if (python_obj != Py_None) AKANTU_DEBUG_WARNING( "functor return a value while none was expected: ignored"); } /* -------------------------------------------------------------------------- */ template <> inline std::string PythonFunctor::convertToAkantu<std::string>(PyObject * python_obj) const { if (!PyString_Check(python_obj)) AKANTU_EXCEPTION("cannot convert object to string"); return PyString_AsString(python_obj); } /* -------------------------------------------------------------------------- */ template <> inline Real PythonFunctor::convertToAkantu<Real>(PyObject * python_obj) const { if (!PyFloat_Check(python_obj)) AKANTU_EXCEPTION("cannot convert object to float"); return PyFloat_AsDouble(python_obj); } /* -------------------------------------------------------------------------- */ template <> inline UInt PythonFunctor::convertToAkantu<UInt>(PyObject * python_obj) const { if (!PyInt_Check(python_obj)) AKANTU_EXCEPTION("cannot convert object to integer"); return PyInt_AsLong(python_obj); } /* -------------------------------------------------------------------------- */ template <typename T> inline std::vector<T> PythonFunctor::convertListToAkantu(PyObject * python_obj) const { std::vector<T> res; UInt size = PyList_Size(python_obj); for (UInt i = 0; i < size; ++i) { PyObject * item = PyList_GET_ITEM(python_obj, i); res.push_back(this->convertToAkantu<T>(item)); } return res; } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_PYTHON_FUNCTOR_INLINE_IMPL_CC__ */ diff --git a/src/solver/petsc_wrapper.hh b/src/solver/petsc_wrapper.hh index d562af998..0a36e6a0b 100644 --- a/src/solver/petsc_wrapper.hh +++ b/src/solver/petsc_wrapper.hh @@ -1,77 +1,77 @@ /** * @file petsc_wrapper.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Wed Oct 07 2015 * * @brief Wrapper of PETSc structures * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_PETSC_WRAPPER_HH__ #define __AKANTU_PETSC_WRAPPER_HH__ /* -------------------------------------------------------------------------- */ #include <mpi.h> #include <petscmat.h> #include <petscvec.h> #include <petscao.h> #include <petscis.h> #include <petscksp.h> -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ struct PETScMatrixWrapper { Mat mat; AO ao; ISLocalToGlobalMapping mapping; /// MPI communicator for PETSc commands MPI_Comm communicator; }; /* -------------------------------------------------------------------------- */ struct PETScSolverWrapper { KSP ksp; Vec solution; Vec rhs; // MPI communicator for PETSc commands MPI_Comm communicator; }; #if not defined(PETSC_CLANGUAGE_CXX) extern int aka_PETScError(int ierr); #define CHKERRXX(x) \ do { \ int error = aka_PETScError(x); \ if (error != 0) { AKANTU_EXCEPTION("Error in PETSC"); } \ } while (0) #endif -__END_AKANTU__ +} // akantu #endif /* __AKANTU_PETSC_WRAPPER_HH__ */ diff --git a/src/solver/solver_petsc.cc b/src/solver/solver_petsc.cc index e7ca06be2..2a7c03b30 100644 --- a/src/solver/solver_petsc.cc +++ b/src/solver/solver_petsc.cc @@ -1,1107 +1,1107 @@ /** * @file solver_petsc.cc * * @author Alejandro M. Aragón <alejandro.aragon@epfl.ch> * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue May 13 2014 * @date last modification: Tue Jan 19 2016 * * @brief Solver class implementation for the petsc solver * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "solver_petsc.hh" #include "dof_manager_petsc.hh" #include "sparse_matrix_petsc.hh" #include "mpi_type_wrapper.hh" /* -------------------------------------------------------------------------- */ #include <petscksp.h> //#include <petscsys.h> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ SolverPETSc::SolverPETSc(DOFManagerPETSc & dof_manager, const ID & matrix_id, const ID & id, const MemoryID & memory_id) : SparseSolver(dof_manager, matrix_id, id, memory_id), dof_manager(dof_manager), matrix(dof_manager.getMatrix(matrix_id)), is_petsc_data_initialized(false) { PetscErrorCode ierr; /// create a solver context ierr = KSPCreate(PETSC_COMM_WORLD, &this->ksp); CHKERRXX(ierr); } /* -------------------------------------------------------------------------- */ SolverPETSc::~SolverPETSc() { AKANTU_DEBUG_IN(); this->destroyInternalData(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolverPETSc::destroyInternalData() { AKANTU_DEBUG_IN(); if (this->is_petsc_data_initialized) { PetscErrorCode ierr; ierr = KSPDestroy(&(this->ksp)); CHKERRXX(ierr); this->is_petsc_data_initialized = false; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolverPETSc::initialize() { AKANTU_DEBUG_IN(); this->is_petsc_data_initialized = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolverPETSc::solve() { AKANTU_DEBUG_IN(); Vec & rhs = this->dof_manager.getResidual(); Vec & solution = this->dof_manager.getGlobalSolution(); PetscErrorCode ierr; ierr = KSPSolve(this->ksp, rhs, solution); CHKERRXX(ierr); AKANTU_DEBUG_OUT(); } // /* -------------------------------------------------------------------------- */ // void SolverPETSc::solve(Array<Real> & solution) { // AKANTU_DEBUG_IN(); // this->solution = &solution; // this->solve(); // PetscErrorCode ierr; // PETScMatrix * petsc_matrix = static_cast<PETScMatrix *>(this->matrix); // // ierr = VecGetOwnershipRange(this->petsc_solver_wrapper->solution, // // solution_begin, solution_end); CHKERRXX(ierr); // // ierr = VecGetArray(this->petsc_solver_wrapper->solution, PetscScalar // // **array); CHKERRXX(ierr); // UInt nb_component = solution.getNbComponent(); // UInt size = solution.getSize(); // for (UInt i = 0; i < size; ++i) { // for (UInt j = 0; j < nb_component; ++j) { // UInt i_local = i * nb_component + j; // if (this->matrix->getDOFSynchronizer().isLocalOrMasterDOF(i_local)) { // Int i_global = // this->matrix->getDOFSynchronizer().getDOFGlobalID(i_local); // ierr = AOApplicationToPetsc(petsc_matrix->getPETScMatrixWrapper()->ao, // 1, &(i_global)); // CHKERRXX(ierr); // ierr = VecGetValues(this->petsc_solver_wrapper->solution, 1, &i_global, // &solution(i, j)); // CHKERRXX(ierr); // } // } // } // synch_registry->synchronize(_gst_solver_solution); // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ void SolverPETSc::setOperators() { AKANTU_DEBUG_IN(); PetscErrorCode ierr; /// set the matrix that defines the linear system and the matrix for /// preconditioning (here they are the same) #if PETSC_VERSION_MAJOR >= 3 && PETSC_VERSION_MINOR >= 5 ierr = KSPSetOperators(this->ksp, this->matrix.getPETScMat(), this->matrix.getPETScMat()); CHKERRXX(ierr); #else ierr = KSPSetOperators(this->ksp, this->matrix.getPETScMat(), this->matrix.getPETScMat(), SAME_NONZERO_PATTERN); CHKERRXX(ierr); #endif /// If this is not called the solution vector is zeroed in the call to /// KSPSolve(). ierr = KSPSetInitialGuessNonzero(this->ksp, PETSC_TRUE); KSPSetFromOptions(this->ksp); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ // void finalize_petsc() { // static bool finalized = false; // if (!finalized) { // cout<<"*** INFO *** PETSc is finalizing..."<<endl; // // finalize PETSc // PetscErrorCode ierr = PetscFinalize();CHKERRCONTINUE(ierr); // finalized = true; // } // } // SolverPETSc::sparse_vector_type // SolverPETSc::operator()(const SolverPETSc::sparse_matrix_type& AA, // const SolverPETSc::sparse_vector_type& bb) { // #ifdef CPPUTILS_VERBOSE // // parallel output stream // Output_stream out; // // timer // cpputils::ctimer timer; // out<<"Inside PETSc solver: "<<timer<<endl; // #endif // #ifdef CPPUTILS_VERBOSE // out<<" Inside operator()(const sparse_matrix_type&, const // sparse_vector_type&)... "<<timer<<endl; // #endif // assert(AA.rows() == bb.size()); // // KSP ksp; //!< linear solver context // Vec b; /* RHS */ // PC pc; /* preconditioner context */ // PetscErrorCode ierr; // PetscInt nlocal; // PetscInt n = bb.size(); // VecScatter ctx; // /* // Create vectors. Note that we form 1 vector from scratch and // then duplicate as needed. For this simple case let PETSc decide how // many elements of the vector are stored on each processor. The second // argument to VecSetSizes() below causes PETSc to decide. // */ // ierr = VecCreate(PETSC_COMM_WORLD,&b);CHKERRCONTINUE(ierr); // ierr = VecSetSizes(b,PETSC_DECIDE,n);CHKERRCONTINUE(ierr); // ierr = VecSetFromOptions(b);CHKERRCONTINUE(ierr); // if (!allocated_) { // ierr = VecDuplicate(b,&x_);CHKERRCONTINUE(ierr); // } else // VecZeroEntries(x_); // #ifdef CPPUTILS_VERBOSE // out<<" Vectors created... "<<timer<<endl; // #endif // /* Set hight-hand-side vector */ // for (sparse_vector_type::const_hash_iterator it = bb.map_.begin(); it != // bb.map_.end(); ++it) { // int row = it->first; // ierr = VecSetValues(b, 1, &row, &it->second, ADD_VALUES); // } // #ifdef CPPUTILS_VERBOSE // out<<" Right hand side set... "<<timer<<endl; // #endif // /* // Assemble vector, using the 2-step process: // VecAssemblyBegin(), VecAssemblyEnd() // Computations can be done while messages are in transition // by placing code between these two statements. // */ // ierr = VecAssemblyBegin(b);CHKERRCONTINUE(ierr); // ierr = VecAssemblyEnd(b);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // out<<" Right-hand-side vector assembled... "<<timer<<endl; // ierr = VecView(b,PETSC_VIEWER_STDOUT_WORLD);CHKERRCONTINUE(ierr); // Vec b_all; // ierr = VecScatterCreateToAll(b, &ctx, &b_all);CHKERRCONTINUE(ierr); // ierr = // VecScatterBegin(ctx,b,b_all,INSERT_VALUES,SCATTER_FORWARD);CHKERRCONTINUE(ierr); // ierr = // VecScatterEnd(ctx,b,b_all,INSERT_VALUES,SCATTER_FORWARD);CHKERRCONTINUE(ierr); // value_type nrm; // VecNorm(b_all,NORM_2,&nrm); // out<<" Norm of right hand side... "<<nrm<<endl; // #endif // /* Identify the starting and ending mesh points on each // processor for the interior part of the mesh. We let PETSc decide // above. */ // // PetscInt rstart,rend; // // ierr = VecGetOwnershipRange(x_,&rstart,&rend);CHKERRCONTINUE(ierr); // ierr = VecGetLocalSize(x_,&nlocal);CHKERRCONTINUE(ierr); // /* // Create matrix. When using MatCreate(), the matrix format can // be specified at runtime. // Performance tuning note: For problems of substantial size, // preallocation of matrix memory is crucial for attaining good // performance. See the matrix chapter of the users manual for details. // We pass in nlocal as the "local" size of the matrix to force it // to have the same parallel layout as the vector created above. // */ // if (!allocated_) { // ierr = MatCreate(PETSC_COMM_WORLD,&A_);CHKERRCONTINUE(ierr); // ierr = MatSetSizes(A_,nlocal,nlocal,n,n);CHKERRCONTINUE(ierr); // ierr = MatSetFromOptions(A_);CHKERRCONTINUE(ierr); // ierr = MatSetUp(A_);CHKERRCONTINUE(ierr); // } else { // // zero-out matrix // MatZeroEntries(A_); // } // /* // Assemble matrix. // The linear system is distributed across the processors by // chunks of contiguous rows, which correspond to contiguous // sections of the mesh on which the problem is discretized. // For matrix assembly, each processor contributes entries for // the part that it owns locally. // */ // #ifdef CPPUTILS_VERBOSE // out<<" Zeroed-out sparse matrix entries... "<<timer<<endl; // #endif // for (sparse_matrix_type::const_hash_iterator it = AA.map_.begin(); it != // AA.map_.end(); ++it) { // // get subscripts // std::pair<size_t,size_t> subs = AA.unhash(it->first); // PetscInt row = subs.first; // PetscInt col = subs.second; // ierr = MatSetValues(A_, 1, &row, 1, &col, &it->second, // ADD_VALUES);CHKERRCONTINUE(ierr); // } // #ifdef CPPUTILS_VERBOSE // out<<" Filled sparse matrix... "<<timer<<endl; // #endif // /* Assemble the matrix */ // ierr = MatAssemblyBegin(A_,MAT_FINAL_ASSEMBLY);CHKERRCONTINUE(ierr); // ierr = MatAssemblyEnd(A_,MAT_FINAL_ASSEMBLY);CHKERRCONTINUE(ierr); // if (!allocated_) { // // set after the first MatAssemblyEnd // // ierr = MatSetOption(A_, MAT_NEW_NONZERO_LOCATIONS, // PETSC_FALSE);CHKERRCONTINUE(ierr); // ierr = MatSetOption(A_, MAT_NEW_NONZERO_ALLOCATION_ERR, // PETSC_FALSE);CHKERRCONTINUE(ierr); // } // #ifdef CPPUTILS_VERBOSE // out<<" Sparse matrix assembled... "<<timer<<endl; // // view matrix // MatView(A_, PETSC_VIEWER_STDOUT_WORLD); // MatNorm(A_,NORM_FROBENIUS,&nrm); // out<<" Norm of stiffness matrix... "<<nrm<<endl; // #endif // /* // Set operators. Here the matrix that defines the linear system // also serves as the preconditioning matrix. // */ // // ierr = // KSPSetOperators(ksp,A_,A_,DIFFERENT_NONZERO_PATTERN);CHKERRCONTINUE(ierr); // ierr = // KSPSetOperators(ksp_,A_,A_,SAME_NONZERO_PATTERN);CHKERRCONTINUE(ierr); // // // // /* // // Set runtime options, e.g., // // -ksp_type <type> -pc_type <type> -ksp_monitor -ksp_rtol <rtol> // // These options will override those specified above as long as // // KSPSetFromOptions() is called _after_ any other customization // // routines. // // */ // // ierr = KSPSetFromOptions(ksp);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // out<<" Solving system... "<<timer<<endl; // #endif // /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Solve the linear system // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ // /* // Solve linear system // */ // ierr = KSPSolve(ksp_,b,x_);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // /* // View solver info; we could instead use the option -ksp_view to // print this info to the screen at the conclusion of KSPSolve(). // */ // ierr = KSPView(ksp_,PETSC_VIEWER_STDOUT_WORLD);CHKERRCONTINUE(ierr); // int iter; // KSPGetIterationNumber(ksp_, &iter); // out<<" System solved in "<<iter<<" iterations... "<<timer<<endl; // KSPConvergedReason reason; // ierr = KSPGetConvergedReason(ksp_,&reason);CHKERRCONTINUE(ierr); // if (reason < 0) // out<<"*** WARNING *** PETSc solver diverged with flag "; // else // out<<"*** INFO *** PETSc solver converged with flag "; // if (reason == KSP_CONVERGED_RTOL) // out<<"KSP_CONVERGED_RTOL"<<endl; // else if (reason == KSP_CONVERGED_ATOL) // out<<"KSP_CONVERGED_ATOL"<<endl; // else if (reason == KSP_CONVERGED_ITS) // out<<"KSP_CONVERGED_ITS"<<endl; // else if (reason == KSP_CONVERGED_CG_NEG_CURVE) // out<<"KSP_CONVERGED_CG_NEG_CURVE"<<endl; // else if (reason == KSP_CONVERGED_CG_CONSTRAINED) // out<<"KSP_CONVERGED_CG_CONSTRAINED"<<endl; // else if (reason == KSP_CONVERGED_STEP_LENGTH) // out<<"KSP_CONVERGED_STEP_LENGTH"<<endl; // else if (reason == KSP_CONVERGED_HAPPY_BREAKDOWN) // out<<"KSP_CONVERGED_HAPPY_BREAKDOWN"<<endl; // else if (reason == KSP_DIVERGED_NULL) // out<<"KSP_DIVERGED_NULL"<<endl; // else if (reason == KSP_DIVERGED_ITS) // out<<"KSP_DIVERGED_ITS"<<endl; // else if (reason == KSP_DIVERGED_DTOL) // out<<"KSP_DIVERGED_DTOL"<<endl; // else if (reason == KSP_DIVERGED_BREAKDOWN) // out<<"KSP_DIVERGED_BREAKDOWN"<<endl; // else if (reason == KSP_DIVERGED_BREAKDOWN_BICG) // out<<"KSP_DIVERGED_BREAKDOWN_BICG"<<endl; // else if (reason == KSP_DIVERGED_NONSYMMETRIC) // out<<"KSP_DIVERGED_NONSYMMETRIC"<<endl; // else if (reason == KSP_DIVERGED_INDEFINITE_PC) // out<<"KSP_DIVERGED_INDEFINITE_PC"<<endl; // else if (reason == KSP_DIVERGED_NAN) // out<<"KSP_DIVERGED_NAN"<<endl; // else if (reason == KSP_DIVERGED_INDEFINITE_MAT) // out<<"KSP_DIVERGED_INDEFINITE_MAT"<<endl; // else if (reason == KSP_CONVERGED_ITERATING) // out<<"KSP_CONVERGED_ITERATING"<<endl; // PetscReal rnorm; // ierr = KSPGetResidualNorm(ksp_,&rnorm);CHKERRCONTINUE(ierr); // out<<"PETSc last residual norm computed: "<<rnorm<<endl; // ierr = VecView(x_,PETSC_VIEWER_STDOUT_WORLD);CHKERRCONTINUE(ierr); // VecNorm(x_,NORM_2,&nrm); // out<<" Norm of solution vector... "<<nrm<<endl; // #endif // /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check solution and clean up // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ // Vec x_all; // ierr = VecScatterCreateToAll(x_, &ctx, &x_all);CHKERRCONTINUE(ierr); // ierr = // VecScatterBegin(ctx,x_,x_all,INSERT_VALUES,SCATTER_FORWARD);CHKERRCONTINUE(ierr); // ierr = // VecScatterEnd(ctx,x_,x_all,INSERT_VALUES,SCATTER_FORWARD);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // out<<" Solution vector scattered... "<<timer<<endl; // VecNorm(x_all,NORM_2,&nrm); // out<<" Norm of scattered vector... "<<nrm<<endl; // // ierr = VecView(x_all,PETSC_VIEWER_STDOUT_WORLD);CHKERRCONTINUE(ierr); // #endif // /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Get values from solution and store them in the object that will be // returned // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ // sparse_vector_type xx(bb.size()); // /* Set solution vector */ // double zero = 0.; // double val; // for (sparse_vector_type::const_hash_iterator it = bb.map_.begin(); it != // bb.map_.end(); ++it) { // int row = it->first; // ierr = VecGetValues(x_all, 1, &row, &val); // if (val != zero) // xx[row] = val; // } // #ifdef CPPUTILS_VERBOSE // out<<" Solution vector copied... "<<timer<<endl; // // out<<" Norm of copied solution vector... "<<norm(xx, // Insert_t)<<endl; // #endif // /* // Free work space. All PETSc objects should be destroyed when they // are no longer needed. // */ // ierr = VecDestroy(&b);CHKERRCONTINUE(ierr); // // ierr = KSPDestroy(&ksp);CHKERRCONTINUE(ierr); // // set allocated flag // if (!allocated_) { // allocated_ = true; // } // #ifdef CPPUTILS_VERBOSE // out<<" Temporary data structures destroyed... "<<timer<<endl; // #endif // return xx; // } // SolverPETSc::sparse_vector_type SolverPETSc::operator()(const // SolverPETSc::sparse_matrix_type& KKpf, const SolverPETSc::sparse_matrix_type& // KKpp, const SolverPETSc::sparse_vector_type& UUp) { // #ifdef CPPUTILS_VERBOSE // // parallel output stream // Output_stream out; // // timer // cpputils::ctimer timer; // out<<"Inside SolverPETSc::operator()(const sparse_matrix&, const // sparse_matrix&, const sparse_vector&). "<<timer<<endl; // #endif // Mat Kpf, Kpp; // Vec Up, Pf, Pp; // PetscErrorCode ierr = // MatCreate(PETSC_COMM_WORLD,&Kpf);CHKERRCONTINUE(ierr); // ierr = MatCreate(PETSC_COMM_WORLD,&Kpp);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // out<<" Allocating memory... "<<timer<<endl; // #endif // ierr = MatSetFromOptions(Kpf);CHKERRCONTINUE(ierr); // ierr = MatSetFromOptions(Kpp);CHKERRCONTINUE(ierr); // ierr = MatSetSizes(Kpf,PETSC_DECIDE,PETSC_DECIDE, KKpf.rows(), // KKpf.columns());CHKERRCONTINUE(ierr); // ierr = MatSetSizes(Kpp,PETSC_DECIDE,PETSC_DECIDE, KKpp.rows(), // KKpp.columns());CHKERRCONTINUE(ierr); // // get number of non-zeros in both diagonal and non-diagonal portions of // the matrix // std::pair<size_t,size_t> Kpf_nz = KKpf.non_zero_off_diagonal(); // std::pair<size_t,size_t> Kpp_nz = KKpp.non_zero_off_diagonal(); // ierr = MatMPIAIJSetPreallocation(Kpf, Kpf_nz.first, PETSC_NULL, // Kpf_nz.second, PETSC_NULL); CHKERRCONTINUE(ierr); // ierr = MatMPIAIJSetPreallocation(Kpp, Kpp_nz.first, PETSC_NULL, // Kpp_nz.second, PETSC_NULL); CHKERRCONTINUE(ierr); // ierr = MatSeqAIJSetPreallocation(Kpf, Kpf_nz.first, PETSC_NULL); // CHKERRCONTINUE(ierr); // ierr = MatSeqAIJSetPreallocation(Kpp, Kpp_nz.first, PETSC_NULL); // CHKERRCONTINUE(ierr); // for (sparse_matrix_type::const_hash_iterator it = KKpf.map_.begin(); it != // KKpf.map_.end(); ++it) { // // get subscripts // std::pair<size_t,size_t> subs = KKpf.unhash(it->first); // int row = subs.first; // int col = subs.second; // ierr = MatSetValues(Kpf, 1, &row, 1, &col, &it->second, // ADD_VALUES);CHKERRCONTINUE(ierr); // } // for (sparse_matrix_type::const_hash_iterator it = KKpp.map_.begin(); it != // KKpp.map_.end(); ++it) { // // get subscripts // std::pair<size_t,size_t> subs = KKpp.unhash(it->first); // int row = subs.first; // int col = subs.second; // ierr = MatSetValues(Kpf, 1, &row, 1, &col, &it->second, // ADD_VALUES);CHKERRCONTINUE(ierr); // } // #ifdef CPPUTILS_VERBOSE // out<<" Filled sparse matrices... "<<timer<<endl; // #endif // /* // Assemble matrix, using the 2-step process: // MatAssemblyBegin(), MatAssemblyEnd() // Computations can be done while messages are in transition // by placing code between these two statements. // */ // ierr = MatAssemblyBegin(Kpf,MAT_FINAL_ASSEMBLY);CHKERRCONTINUE(ierr); // ierr = MatAssemblyBegin(Kpp,MAT_FINAL_ASSEMBLY);CHKERRCONTINUE(ierr); // ierr = MatAssemblyEnd(Kpf,MAT_FINAL_ASSEMBLY);CHKERRCONTINUE(ierr); // ierr = MatAssemblyEnd(Kpp,MAT_FINAL_ASSEMBLY);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // out<<" Sparse matrices assembled... "<<timer<<endl; // #endif // ierr = VecCreate(PETSC_COMM_WORLD,&Up);CHKERRCONTINUE(ierr); // ierr = VecSetSizes(Up,PETSC_DECIDE, UUp.size());CHKERRCONTINUE(ierr); // ierr = VecSetFromOptions(Up);CHKERRCONTINUE(ierr); // ierr = VecCreate(PETSC_COMM_WORLD,&Pf);CHKERRCONTINUE(ierr); // ierr = VecSetSizes(Pf,PETSC_DECIDE, KKpf.rows());CHKERRCONTINUE(ierr); // ierr = VecSetFromOptions(Pf);CHKERRCONTINUE(ierr); // ierr = VecDuplicate(Pf,&Pp);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // out<<" Vectors created... "<<timer<<endl; // #endif // /* Set hight-hand-side vector */ // for (sparse_vector_type::const_hash_iterator it = UUp.map_.begin(); it != // UUp.map_.end(); ++it) { // int row = it->first; // ierr = VecSetValues(Up, 1, &row, &it->second, ADD_VALUES); // } // /* // Assemble vector, using the 2-step process: // VecAssemblyBegin(), VecAssemblyEnd() // Computations can be done while messages are in transition // by placing code between these two statements. // */ // ierr = VecAssemblyBegin(Up);CHKERRCONTINUE(ierr); // ierr = VecAssemblyEnd(Up);CHKERRCONTINUE(ierr); // // add Kpf*Uf // ierr = MatMult(Kpf, x_, Pf); // // add Kpp*Up // ierr = MatMultAdd(Kpp, Up, Pf, Pp); // #ifdef CPPUTILS_VERBOSE // out<<" Matrices multiplied... "<<timer<<endl; // #endif // VecScatter ctx; // Vec Pp_all; // ierr = VecScatterCreateToAll(Pp, &ctx, &Pp_all);CHKERRCONTINUE(ierr); // ierr = // VecScatterBegin(ctx,Pp,Pp_all,INSERT_VALUES,SCATTER_FORWARD);CHKERRCONTINUE(ierr); // ierr = // VecScatterEnd(ctx,Pp,Pp_all,INSERT_VALUES,SCATTER_FORWARD);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // out<<" Vector scattered... "<<timer<<endl; // #endif // /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Get values from solution and store them in the object that will be // returned // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ // sparse_vector_type pp(KKpf.rows()); // // get reaction vector // for (int i=0; i<KKpf.rows(); ++i) { // PetscScalar v; // ierr = VecGetValues(Pp_all, 1, &i, &v); // if (v != PetscScalar()) // pp[i] = v; // } // #ifdef CPPUTILS_VERBOSE // out<<" Vector copied... "<<timer<<endl; // #endif // ierr = MatDestroy(&Kpf);CHKERRCONTINUE(ierr); // ierr = MatDestroy(&Kpp);CHKERRCONTINUE(ierr); // ierr = VecDestroy(&Up);CHKERRCONTINUE(ierr); // ierr = VecDestroy(&Pf);CHKERRCONTINUE(ierr); // ierr = VecDestroy(&Pp);CHKERRCONTINUE(ierr); // ierr = VecDestroy(&Pp_all);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // out<<" Temporary data structures destroyed... "<<timer<<endl; // #endif // return pp; // } // SolverPETSc::sparse_vector_type SolverPETSc::operator()(const // SolverPETSc::sparse_vector_type& aa, const SolverPETSc::sparse_vector_type& // bb) { // assert(aa.size() == bb.size()); // #ifdef CPPUTILS_VERBOSE // // parallel output stream // Output_stream out; // // timer // cpputils::ctimer timer; // out<<"Inside SolverPETSc::operator()(const sparse_vector&, const // sparse_vector&). "<<timer<<endl; // #endif // Vec r; // PetscErrorCode ierr = VecCreate(PETSC_COMM_WORLD,&r);CHKERRCONTINUE(ierr); // ierr = VecSetSizes(r,PETSC_DECIDE, aa.size());CHKERRCONTINUE(ierr); // ierr = VecSetFromOptions(r);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // out<<" Vectors created... "<<timer<<endl; // #endif // // set values // for (sparse_vector_type::const_hash_iterator it = aa.map_.begin(); it != // aa.map_.end(); ++it) { // int row = it->first; // ierr = VecSetValues(r, 1, &row, &it->second, ADD_VALUES); // } // for (sparse_vector_type::const_hash_iterator it = bb.map_.begin(); it != // bb.map_.end(); ++it) { // int row = it->first; // ierr = VecSetValues(r, 1, &row, &it->second, ADD_VALUES); // } // /* // Assemble vector, using the 2-step process: // VecAssemblyBegin(), VecAssemblyEnd() // Computations can be done while messages are in transition // by placing code between these two statements. // */ // ierr = VecAssemblyBegin(r);CHKERRCONTINUE(ierr); // ierr = VecAssemblyEnd(r);CHKERRCONTINUE(ierr); // sparse_vector_type rr(aa.size()); // for (sparse_vector_type::const_hash_iterator it = aa.map_.begin(); it != // aa.map_.end(); ++it) { // int row = it->first; // ierr = VecGetValues(r, 1, &row, &rr[row]); // } // for (sparse_vector_type::const_hash_iterator it = bb.map_.begin(); it != // bb.map_.end(); ++it) { // int row = it->first; // ierr = VecGetValues(r, 1, &row, &rr[row]); // } // #ifdef CPPUTILS_VERBOSE // out<<" Vector copied... "<<timer<<endl; // #endif // ierr = VecDestroy(&r);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // out<<" Temporary data structures destroyed... "<<timer<<endl; // #endif // return rr; // } // SolverPETSc::value_type SolverPETSc::norm(const // SolverPETSc::sparse_matrix_type& aa, Element_insertion_type flag) { // #ifdef CPPUTILS_VERBOSE // // parallel output stream // Output_stream out; // // timer // cpputils::ctimer timer; // out<<"Inside SolverPETSc::norm(const sparse_matrix&). "<<timer<<endl; // #endif // Mat r; // PetscErrorCode ierr = MatCreate(PETSC_COMM_WORLD,&r);CHKERRCONTINUE(ierr); // ierr = MatSetSizes(r,PETSC_DECIDE,PETSC_DECIDE, aa.rows(), // aa.columns());CHKERRCONTINUE(ierr); // ierr = MatSetFromOptions(r);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // out<<" Matrix created... "<<timer<<endl; // #endif // // set values // for (sparse_vector_type::const_hash_iterator it = aa.map_.begin(); it != // aa.map_.end(); ++it) { // // get subscripts // std::pair<size_t,size_t> subs = aa.unhash(it->first); // int row = subs.first; // int col = subs.second; // if (flag == Add_t) // ierr = MatSetValues(r, 1, &row, 1, &col, &it->second, ADD_VALUES); // else if (flag == Insert_t) // ierr = MatSetValues(r, 1, &row, 1, &col, &it->second, INSERT_VALUES); // CHKERRCONTINUE(ierr); // } // #ifdef CPPUTILS_VERBOSE // out<<" Matrix filled..."<<timer<<endl; // #endif // /* // Assemble vector, using the 2-step process: // VecAssemblyBegin(), VecAssemblyEnd() // Computations can be done while messages are in transition // by placing code between these two statements. // */ // ierr = MatAssemblyBegin(r,MAT_FINAL_ASSEMBLY);CHKERRCONTINUE(ierr); // ierr = MatAssemblyEnd(r,MAT_FINAL_ASSEMBLY);CHKERRCONTINUE(ierr); // value_type nrm; // MatNorm(r,NORM_FROBENIUS,&nrm); // #ifdef CPPUTILS_VERBOSE // out<<" Norm computed... "<<timer<<endl; // #endif // ierr = MatDestroy(&r);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // out<<" Temporary data structures destroyed... "<<timer<<endl; // #endif // return nrm; // } // SolverPETSc::value_type SolverPETSc::norm(const // SolverPETSc::sparse_vector_type& aa, Element_insertion_type flag) { // #ifdef CPPUTILS_VERBOSE // // parallel output stream // Output_stream out; // // timer // cpputils::ctimer timer; // out<<"Inside SolverPETSc::norm(const sparse_vector&). "<<timer<<endl; // #endif // Vec r; // PetscErrorCode ierr = VecCreate(PETSC_COMM_WORLD,&r);CHKERRCONTINUE(ierr); // ierr = VecSetSizes(r,PETSC_DECIDE, aa.size());CHKERRCONTINUE(ierr); // ierr = VecSetFromOptions(r);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // out<<" Vector created... "<<timer<<endl; // #endif // // set values // for (sparse_vector_type::const_hash_iterator it = aa.map_.begin(); it != // aa.map_.end(); ++it) { // int row = it->first; // if (flag == Add_t) // ierr = VecSetValues(r, 1, &row, &it->second, ADD_VALUES); // else if (flag == Insert_t) // ierr = VecSetValues(r, 1, &row, &it->second, INSERT_VALUES); // CHKERRCONTINUE(ierr); // } // #ifdef CPPUTILS_VERBOSE // out<<" Vector filled..."<<timer<<endl; // #endif // /* // Assemble vector, using the 2-step process: // VecAssemblyBegin(), VecAssemblyEnd() // Computations can be done while messages are in transition // by placing code between these two statements. // */ // ierr = VecAssemblyBegin(r);CHKERRCONTINUE(ierr); // ierr = VecAssemblyEnd(r);CHKERRCONTINUE(ierr); // value_type nrm; // VecNorm(r,NORM_2,&nrm); // #ifdef CPPUTILS_VERBOSE // out<<" Norm computed... "<<timer<<endl; // #endif // ierr = VecDestroy(&r);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // out<<" Temporary data structures destroyed... "<<timer<<endl; // #endif // return nrm; // } // // // ///* // -------------------------------------------------------------------------- */ // //SolverMumps::SolverMumps(SparseMatrix & matrix, // // const ID & id, // // const MemoryID & memory_id) : // //Solver(matrix, id, memory_id), is_mumps_data_initialized(false), // rhs_is_local(true) { // // AKANTU_DEBUG_IN(); // // // //#ifdef AKANTU_USE_MPI // // parallel_method = SolverMumpsOptions::_fully_distributed; // //#else //AKANTU_USE_MPI // // parallel_method = SolverMumpsOptions::_master_slave_distributed; // //#endif //AKANTU_USE_MPI // // // // CommunicatorEventHandler & comm_event_handler = *this; // // // // communicator.registerEventHandler(comm_event_handler); // // // // AKANTU_DEBUG_OUT(); // //} // // // ///* // -------------------------------------------------------------------------- */ // //SolverMumps::~SolverMumps() { // // AKANTU_DEBUG_IN(); // // // // AKANTU_DEBUG_OUT(); // //} // // // ///* // -------------------------------------------------------------------------- */ // //void SolverMumps::destroyMumpsData() { // // AKANTU_DEBUG_IN(); // // // // if(is_mumps_data_initialized) { // // mumps_data.job = _smj_destroy; // destroy // // dmumps_c(&mumps_data); // // is_mumps_data_initialized = false; // // } // // // // AKANTU_DEBUG_OUT(); // //} // // // ///* // -------------------------------------------------------------------------- */ // //void SolverMumps::onCommunicatorFinalize(const StaticCommunicator & comm) { // // AKANTU_DEBUG_IN(); // // // // try{ // // const StaticCommunicatorMPI & comm_mpi = // // dynamic_cast<const StaticCommunicatorMPI // &>(comm.getRealStaticCommunicator()); // // if(mumps_data.comm_fortran == // MPI_Comm_c2f(comm_mpi.getMPICommunicator())) // // destroyMumpsData(); // // } catch(...) {} // // // // AKANTU_DEBUG_OUT(); // //} // // // ///* // -------------------------------------------------------------------------- */ // //void SolverMumps::initMumpsData(SolverMumpsOptions::ParallelMethod // parallel_method) { // // switch(parallel_method) { // // case SolverMumpsOptions::_fully_distributed: // // icntl(18) = 3; //fully distributed // // icntl(28) = 0; //automatic choice // // // // mumps_data.nz_loc = matrix->getNbNonZero(); // // mumps_data.irn_loc = matrix->getIRN().values; // // mumps_data.jcn_loc = matrix->getJCN().values; // // break; // // case SolverMumpsOptions::_master_slave_distributed: // // if(prank == 0) { // // mumps_data.nz = matrix->getNbNonZero(); // // mumps_data.irn = matrix->getIRN().values; // // mumps_data.jcn = matrix->getJCN().values; // // } else { // // mumps_data.nz = 0; // // mumps_data.irn = NULL; // // mumps_data.jcn = NULL; // // // // icntl(18) = 0; //centralized // // icntl(28) = 0; //sequential analysis // // } // // break; // // } // //} // // // ///* // -------------------------------------------------------------------------- */ // //void SolverMumps::initialize(SolverOptions & options) { // // AKANTU_DEBUG_IN(); // // // // mumps_data.par = 1; // // // // if(SolverMumpsOptions * opt = dynamic_cast<SolverMumpsOptions // *>(&options)) { // // if(opt->parallel_method == // SolverMumpsOptions::_master_slave_distributed) { // // mumps_data.par = 0; // // } // // } // // // // mumps_data.sym = 2 * (matrix->getSparseMatrixType() == _symmetric); // // prank = communicator.whoAmI(); // //#ifdef AKANTU_USE_MPI // // mumps_data.comm_fortran = MPI_Comm_c2f(dynamic_cast<const // StaticCommunicatorMPI // &>(communicator.getRealStaticCommunicator()).getMPICommunicator()); // //#endif // // // // if(AKANTU_DEBUG_TEST(dblTrace)) { // // icntl(1) = 2; // // icntl(2) = 2; // // icntl(3) = 2; // // icntl(4) = 4; // // } // // // // mumps_data.job = _smj_initialize; //initialize // // dmumps_c(&mumps_data); // // is_mumps_data_initialized = true; // // // // /* // ------------------------------------------------------------------------ */ // // UInt size = matrix->getSize(); // // // // if(prank == 0) { // // std::stringstream sstr_rhs; sstr_rhs << id << ":rhs"; // // rhs = &(alloc<Real>(sstr_rhs.str(), size, 1, REAL_INIT_VALUE)); // // } else { // // rhs = NULL; // // } // // // // /// No outputs // // icntl(1) = 0; // // icntl(2) = 0; // // icntl(3) = 0; // // icntl(4) = 0; // // mumps_data.nz_alloc = 0; // // // // if (AKANTU_DEBUG_TEST(dblDump)) icntl(4) = 4; // // // // mumps_data.n = size; // // // // if(AKANTU_DEBUG_TEST(dblDump)) { // // strcpy(mumps_data.write_problem, "mumps_matrix.mtx"); // // } // // // // /* // ------------------------------------------------------------------------ */ // // // Default Scaling // // icntl(8) = 77; // // // // icntl(5) = 0; // Assembled matrix // // // // SolverMumpsOptions * opt = dynamic_cast<SolverMumpsOptions *>(&options); // // if(opt) // // parallel_method = opt->parallel_method; // // // // initMumpsData(parallel_method); // // // // mumps_data.job = _smj_analyze; //analyze // // dmumps_c(&mumps_data); // // // // AKANTU_DEBUG_OUT(); // //} // // // ///* // -------------------------------------------------------------------------- */ // //void SolverMumps::setRHS(Array<Real> & rhs) { // // if(prank == 0) { // // matrix->getDOFSynchronizer().gather(rhs, 0, this->rhs); // // } else { // // matrix->getDOFSynchronizer().gather(rhs, 0); // // } // //} // // // ///* // -------------------------------------------------------------------------- */ // //void SolverMumps::solve() { // // AKANTU_DEBUG_IN(); // // // // if(parallel_method == SolverMumpsOptions::_fully_distributed) // // mumps_data.a_loc = matrix->getA().values; // // else // // if(prank == 0) { // // mumps_data.a = matrix->getA().values; // // } // // // // if(prank == 0) { // // mumps_data.rhs = rhs->values; // // } // // // // /// Default centralized dense second member // // icntl(20) = 0; // // icntl(21) = 0; // // // // mumps_data.job = _smj_factorize_solve; //solve // // dmumps_c(&mumps_data); // // // // AKANTU_DEBUG_ASSERT(info(1) != -10, "Singular matrix"); // // AKANTU_DEBUG_ASSERT(info(1) == 0, // // "Error in mumps during solve process, check mumps // user guide INFO(1) =" // // << info(1)); // // // // AKANTU_DEBUG_OUT(); // //} // // // ///* // -------------------------------------------------------------------------- */ // //void SolverMumps::solve(Array<Real> & solution) { // // AKANTU_DEBUG_IN(); // // // // solve(); // // // // if(prank == 0) { // // matrix->getDOFSynchronizer().scatter(solution, 0, this->rhs); // // } else { // // matrix->getDOFSynchronizer().scatter(solution, 0); // // } // // // // AKANTU_DEBUG_OUT(); // //} -__END_AKANTU__ +} // akantu diff --git a/src/solver/solver_petsc.hh b/src/solver/solver_petsc.hh index 8394d52e8..a992347cd 100644 --- a/src/solver/solver_petsc.hh +++ b/src/solver/solver_petsc.hh @@ -1,182 +1,182 @@ /** * @file solver_petsc.hh * * @author Alejandro M. Aragón <alejandro.aragon@epfl.ch> * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue May 13 2014 * @date last modification: Wed Oct 07 2015 * * @brief Solver class interface for the petsc solver * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "sparse_solver.hh" /* -------------------------------------------------------------------------- */ #include <petscksp.h> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLVER_PETSC_HH__ #define __AKANTU_SOLVER_PETSC_HH__ namespace akantu { class SparseMatrixPETSc; class DOFManagerPETSc; } -__BEGIN_AKANTU__ +namespace akantu { class SolverPETSc : public SparseSolver { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SolverPETSc(DOFManagerPETSc & dof_manager, const ID & matrix_id, const ID & id = "solver_petsc", const MemoryID & memory_id = 0); virtual ~SolverPETSc(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// create the solver context and set the matrices virtual void initialize(); virtual void setOperators(); virtual void setRHS(Array<Real> & rhs); virtual void solve(); virtual void solve(Array<Real> & solution); private: /// clean the petsc data virtual void destroyInternalData(); private: /// DOFManager correctly typed DOFManagerPETSc & dof_manager; /// PETSc linear solver KSP ksp; /// Matrix defining the system of equations SparseMatrixPETSc & matrix; /// specify if the petsc_data is initialized or not bool is_petsc_data_initialized; }; // SolverPETSc(int argc, char *argv[]) : allocated_(false) { // /* // Set linear solver defaults for this problem (optional). // - By extracting the KSP and PC contexts from the KSP context, // we can then directly call any KSP and PC routines to set // various options. // - The following four statements are optional; all of these // parameters could alternatively be specified at runtime via // KSPSetFromOptions(); // */ // // ierr = KSPGetPC(ksp_,&pc);CHKERRCONTINUE(ierr); // // ierr = PCSetType(pc,PCILU);CHKERRCONTINUE(ierr); // // ierr = PCSetType(pc,PCJACOBI);CHKERRCONTINUE(ierr); // ierr = // KSPSetTolerances(ksp_,1.e-5,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRCONTINUE(ierr); // } // //! Overload operator() to solve system of linear equations // sparse_vector_type operator()(const sparse_matrix_type& AA, const // sparse_vector_type& bb); // //! Overload operator() to obtain reaction vector // sparse_vector_type operator()(const sparse_matrix_type& Kpf, const // sparse_matrix_type& Kpp, const sparse_vector_type& Up); // //! Overload operator() to obtain the addition two vectors // sparse_vector_type operator()(const sparse_vector_type& aa, const // sparse_vector_type& bb); // value_type norm(const sparse_matrix_type& aa, Element_insertion_type it = // Add_t); // value_type norm(const sparse_vector_type& aa, Element_insertion_type it = // Add_t); // // NOTE: the destructor will return an error if it is called after // MPI_Finalize is // // called because it uses collect communication to free-up allocated // memory. // ~SolverPETSc() { // static bool exit = false; // if (!exit) { // // add finalize PETSc function at exit // atexit(finalize); // exit = true; // } // if (allocated_) { // PetscErrorCode ierr = MatDestroy(&A_);CHKERRCONTINUE(ierr); // ierr = VecDestroy(&x_);CHKERRCONTINUE(ierr); // ierr = KSPDestroy(&ksp_);CHKERRCONTINUE(ierr); // } // } // /* from the PETSc library, these are the options that can be passed // to the command line // Options Database Keys // -options_table - Calls PetscOptionsView() // -options_left - Prints unused options that remain in the // database // -objects_left - Prints list of all objects that have not // been freed // -mpidump - Calls PetscMPIDump() // -malloc_dump - Calls PetscMallocDump() // -malloc_info - Prints total memory usage // -malloc_log - Prints summary of memory usage // Options Database Keys for Profiling // -log_summary [filename] - Prints summary of flop and timing // information to screen. // If the filename is specified the summary is written to the file. See // PetscLogView(). // -log_summary_python [filename] - Prints data on of flop and timing usage // to a file or screen. // -log_all [filename] - Logs extensive profiling information See // PetscLogDump(). // -log [filename] - Logs basic profiline information See // PetscLogDump(). // -log_sync - Log the synchronization in scatters, // inner products and norms // -log_mpe [filename] - Creates a logfile viewable by the utility // Upshot/Nupshot (in MPICH distribution) // } // } // }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_SOLVER_PETSC_HH__ */ diff --git a/src/solver/sparse_matrix.cc b/src/solver/sparse_matrix.cc index ee229bde1..c24d5d855 100644 --- a/src/solver/sparse_matrix.cc +++ b/src/solver/sparse_matrix.cc @@ -1,80 +1,80 @@ /** * @file sparse_matrix.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Dec 13 2010 * @date last modification: Mon Nov 16 2015 * * @brief implementation of the SparseMatrix class * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <fstream> /* -------------------------------------------------------------------------- */ #include "dof_manager.hh" #include "sparse_matrix.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ SparseMatrix::SparseMatrix(DOFManager & dof_manager, const MatrixType & matrix_type, const ID & id) : id(id), _dof_manager(dof_manager), matrix_type(matrix_type), size(dof_manager.getSystemSize()), nb_non_zero(0) { AKANTU_DEBUG_IN(); const auto & comm = _dof_manager.getCommunicator(); this->nb_proc = comm.getNbProc(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseMatrix::SparseMatrix(const SparseMatrix & matrix, const ID & id) : SparseMatrix(matrix._dof_manager, matrix.matrix_type, id) { nb_non_zero = matrix.nb_non_zero; } /* -------------------------------------------------------------------------- */ SparseMatrix::~SparseMatrix() {} /* -------------------------------------------------------------------------- */ Array<Real> & operator*=(Array<Real> & vect, const SparseMatrix & mat) { Array<Real> tmp(vect.getSize(), vect.getNbComponent(), 0.); mat.matVecMul(vect, tmp); vect.copy(tmp); return vect; } /* -------------------------------------------------------------------------- */ void SparseMatrix::add(const SparseMatrix & B, Real alpha) { B.addMeTo(*this, alpha); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/solver/sparse_matrix_aij.cc b/src/solver/sparse_matrix_aij.cc index 9f8e3f1c7..feb34c5cd 100644 --- a/src/solver/sparse_matrix_aij.cc +++ b/src/solver/sparse_matrix_aij.cc @@ -1,225 +1,225 @@ /** * @file sparse_matrix_aij.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Tue Aug 18 16:31:23 2015 * * @brief Implementation of the AIJ sparse matrix * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "sparse_matrix_aij.hh" #include "dof_manager_default.hh" #include "dof_synchronizer.hh" #include "terms_to_assemble.hh" /* -------------------------------------------------------------------------- */ #include <fstream> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ SparseMatrixAIJ::SparseMatrixAIJ(DOFManagerDefault & dof_manager, const MatrixType & matrix_type, const ID & id) : SparseMatrix(dof_manager, matrix_type, id), dof_manager(dof_manager), irn(0, 1, id + ":irn"), jcn(0, 1, id + ":jcn"), a(0, 1, id + ":a"), profile_release(1), value_release(1) {} /* -------------------------------------------------------------------------- */ SparseMatrixAIJ::SparseMatrixAIJ(const SparseMatrixAIJ & matrix, const ID & id) : SparseMatrix(matrix, id), dof_manager(matrix.dof_manager), irn(matrix.irn, true, id + ":irn"), jcn(matrix.jcn, true, id + ":jcn"), a(matrix.a, true, id + ":a"), profile_release(1), value_release(1) {} /* -------------------------------------------------------------------------- */ SparseMatrixAIJ::~SparseMatrixAIJ() {} /* -------------------------------------------------------------------------- */ void SparseMatrixAIJ::applyBoundary(Real block_val) { AKANTU_DEBUG_IN(); // clang-format off const auto & blocked_dofs = this->dof_manager.getGlobalBlockedDOFs(); auto irn_it = irn.begin(); auto jcn_it = jcn.begin(); auto a_it = a.begin(); auto a_end = a.end(); for (;a_it != a_end; ++a_it, ++irn_it, ++jcn_it) { UInt ni = this->dof_manager.globalToLocalEquationNumber(*irn_it - 1); UInt nj = this->dof_manager.globalToLocalEquationNumber(*jcn_it - 1); if (blocked_dofs(ni) || blocked_dofs(nj)) { *a_it = *irn_it != *jcn_it ? 0. : this->dof_manager.isLocalOrMasterDOF(ni) ? block_val : 0.; } } this->value_release++; // clang-format on AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrixAIJ::saveProfile(const std::string & filename) const { AKANTU_DEBUG_IN(); std::ofstream outfile; outfile.open(filename.c_str()); UInt m = this->size; outfile << "%%MatrixMarket matrix coordinate pattern"; if (this->matrix_type == _symmetric) outfile << " symmetric"; else outfile << " general"; outfile << std::endl; outfile << m << " " << m << " " << this->nb_non_zero << std::endl; for (UInt i = 0; i < this->nb_non_zero; ++i) { outfile << this->irn.storage()[i] << " " << this->jcn.storage()[i] << " 1" << std::endl; } outfile.close(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrixAIJ::saveMatrix(const std::string & filename) const { AKANTU_DEBUG_IN(); // open and set the properties of the stream std::ofstream outfile; outfile.open(filename.c_str()); outfile.precision(std::numeric_limits<Real>::digits10); // write header outfile << "%%MatrixMarket matrix coordinate real"; if (this->matrix_type == _symmetric) outfile << " symmetric"; else outfile << " general"; outfile << std::endl; outfile << this->size << " " << this->size << " " << this->nb_non_zero << std::endl; // write content for (UInt i = 0; i < this->nb_non_zero; ++i) { outfile << this->irn(i) << " " << this->jcn(i) << " " << this->a(i) << std::endl; } // time to end outfile.close(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrixAIJ::matVecMul(const Array<Real> & x, Array<Real> & y, Real alpha, Real beta) const { AKANTU_DEBUG_IN(); y *= beta; auto i_it = this->irn.begin(); auto j_it = this->jcn.begin(); auto a_it = this->a.begin(); auto a_end = this->a.end(); auto x_it = x.begin_reinterpret(x.getSize() * x.getNbComponent()); auto y_it = y.begin_reinterpret(x.getSize() * x.getNbComponent()); for (; a_it != a_end; ++i_it, ++j_it, ++a_it) { Int i = this->dof_manager.globalToLocalEquationNumber(*i_it - 1); Int j = this->dof_manager.globalToLocalEquationNumber(*j_it - 1); const Real & A = *a_it; y_it[i] += alpha * A * x_it[j]; if ((this->matrix_type == _symmetric) && (i != j)) y_it[j] += alpha * A * x_it[i]; } if (this->dof_manager.hasSynchronizer()) this->dof_manager.getSynchronizer().reduceSynchronize<AddOperation>(y); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrixAIJ::copyContent(const SparseMatrix & matrix) { AKANTU_DEBUG_IN(); const SparseMatrixAIJ & mat = dynamic_cast<const SparseMatrixAIJ &>(matrix); AKANTU_DEBUG_ASSERT(nb_non_zero == mat.getNbNonZero(), "The to matrix don't have the same profiles"); memcpy(a.storage(), mat.getA().storage(), nb_non_zero * sizeof(Real)); this->value_release++; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class MatrixType> void SparseMatrixAIJ::addMeToTemplated(MatrixType & B, Real alpha) const { auto i_it = this->irn.begin(); auto j_it = this->jcn.begin(); auto a_it = this->a.begin(); auto a_end = this->a.end(); for (; a_it != a_end; ++a_it, ++i_it, ++j_it) { const Int & i = *i_it; const Int & j = *j_it; const Real & A_ij = *a_it; B.addToMatrix(i - 1, j - 1, alpha * A_ij); } } /* -------------------------------------------------------------------------- */ void SparseMatrixAIJ::addMeTo(SparseMatrix & B, Real alpha) const { if (SparseMatrixAIJ * B_aij = dynamic_cast<SparseMatrixAIJ *>(&B)) { this->addMeToTemplated<SparseMatrixAIJ>(*B_aij, alpha); } else { // this->addMeToTemplated<SparseMatrix>(*this, alpha); } } /* -------------------------------------------------------------------------- */ void SparseMatrixAIJ::mul(Real alpha) { this->a *= alpha; this->value_release++; } /* -------------------------------------------------------------------------- */ void SparseMatrixAIJ::clear() { a.set(0.); this->value_release++; } -__END_AKANTU__ +} // akantu diff --git a/src/solver/sparse_matrix_aij.hh b/src/solver/sparse_matrix_aij.hh index 5c848bdc8..7821f452d 100644 --- a/src/solver/sparse_matrix_aij.hh +++ b/src/solver/sparse_matrix_aij.hh @@ -1,181 +1,181 @@ /** * @file sparse_matrix_aij.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Mon Aug 17 21:22:57 2015 * * @brief AIJ implementation of the SparseMatrix (this the format used by Mumps) * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" #include "aka_common.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ #include <unordered_map> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SPARSE_MATRIX_AIJ_HH__ #define __AKANTU_SPARSE_MATRIX_AIJ_HH__ namespace akantu { class DOFManagerDefault; class TermsToAssemble; } -__BEGIN_AKANTU__ +namespace akantu { class SparseMatrixAIJ : public SparseMatrix { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SparseMatrixAIJ(DOFManagerDefault & dof_manager, const MatrixType & matrix_type, const ID & id = "sparse_matrix_aij"); SparseMatrixAIJ(const SparseMatrixAIJ & matrix, const ID & id = "sparse_matrix_aij"); virtual ~SparseMatrixAIJ(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// remove the existing profile inline void clearProfile(); /// add a non-zero element virtual inline UInt addToProfile(UInt i, UInt j); /// set the matrix to 0 virtual void clear(); /// assemble a local matrix in the sparse one virtual inline void addToMatrix(UInt i, UInt j, Real value); /// set the size of the matrix void resize(UInt size) { this->size = size; } /// modify the matrix to "remove" the blocked dof virtual void applyBoundary(Real block_val = 1.); /// save the profil in a file using the MatrixMarket file format virtual void saveProfile(const std::string & filename) const; /// save the matrix in a file using the MatrixMarket file format virtual void saveMatrix(const std::string & filename) const; /// copy assuming the profile are the same virtual void copyContent(const SparseMatrix & matrix); /// multiply the matrix by a scalar void mul(Real alpha); /// add matrix *this += B // virtual void add(const SparseMatrix & matrix, Real alpha); /// Equivalent of *gemv in blas virtual void matVecMul(const Array<Real> & x, Array<Real> & y, Real alpha = 1., Real beta = 0.) const; /* ------------------------------------------------------------------------ */ /// accessor to A_{ij} - if (i, j) not present it returns 0 inline Real operator()(UInt i, UInt j) const; /// accessor to A_{ij} - if (i, j) not present it fails, (i, j) should be /// first added to the profile inline Real & operator()(UInt i, UInt j); protected: /// This is the revert of add B += \alpha * *this; virtual void addMeTo(SparseMatrix & B, Real alpha) const; private: /// This is just to inline the addToMatrix function template <class MatrixType> void addMeToTemplated(MatrixType & B, Real alpha) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(IRN, irn, const Array<Int> &); AKANTU_GET_MACRO(JCN, jcn, const Array<Int> &); AKANTU_GET_MACRO(A, a, const Array<Real> &); /// The release changes at each call of a function that changes the profile, /// it in increasing but could overflow so it should be checked as /// (my_release != release) and not as (my_release < release) AKANTU_GET_MACRO(ProfileRelease, profile_release, UInt); AKANTU_GET_MACRO(ValueRelease, value_release, UInt); virtual UInt getRelease() const { return value_release; } protected: using KeyCOO = std::pair<UInt, UInt>; using coordinate_list_map = std::unordered_map<KeyCOO, UInt>; /// get the pair corresponding to (i, j) inline KeyCOO key(UInt i, UInt j) const { if (this->matrix_type == _symmetric && (i > j)) return std::make_pair(j, i); return std::make_pair(i, j); } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: DOFManagerDefault & dof_manager; /// row indexes Array<Int> irn; /// column indexes Array<Int> jcn; /// values : A[k] = Matrix[irn[k]][jcn[k]] Array<Real> a; /// Profile release UInt profile_release; /// Value release UInt value_release; /* * map for (i, j) -> k correspondence */ coordinate_list_map irn_jcn_k; }; -__END_AKANTU__ +} // akantu /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "sparse_matrix_aij_inline_impl.cc" #endif /* __AKANTU_SPARSE_MATRIX_AIJ_HH__ */ diff --git a/src/solver/sparse_matrix_aij_inline_impl.cc b/src/solver/sparse_matrix_aij_inline_impl.cc index 17d4ded0d..493f9627d 100644 --- a/src/solver/sparse_matrix_aij_inline_impl.cc +++ b/src/solver/sparse_matrix_aij_inline_impl.cc @@ -1,111 +1,111 @@ /** * @file sparse_matrix_aij_inline_impl.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Tue Aug 18 00:42:45 2015 * * @brief Implementation of inline functions of SparseMatrixAIJ * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SPARSE_MATRIX_AIJ_INLINE_IMPL_CC__ #define __AKANTU_SPARSE_MATRIX_AIJ_INLINE_IMPL_CC__ -__BEGIN_AKANTU__ +namespace akantu { inline UInt SparseMatrixAIJ::addToProfile(UInt i, UInt j) { KeyCOO jcn_irn = this->key(i, j); coordinate_list_map::iterator it = this->irn_jcn_k.find(jcn_irn); if (!(it == this->irn_jcn_k.end())) return it->second; if(i + 1 > this->size) this->size = i + 1; if(j + 1 > this->size) this->size = j + 1; this->irn.push_back(i + 1); this->jcn.push_back(j + 1); this->a.push_back(0.); this->irn_jcn_k[jcn_irn] = this->nb_non_zero; (this->nb_non_zero)++; this->profile_release++; this->value_release++; return (this->nb_non_zero - 1); } /* -------------------------------------------------------------------------- */ inline void SparseMatrixAIJ::clearProfile() { SparseMatrix::clearProfile(); this->irn_jcn_k.clear(); this->irn.resize(0); this->jcn.resize(0); this->a.resize(0); this->size = 0; this->profile_release++; this->value_release++; } /* -------------------------------------------------------------------------- */ inline void SparseMatrixAIJ::addToMatrix(UInt i, UInt j, Real value) { UInt idx = this->addToProfile(i, j); this->a(idx) += value; this->value_release++; } /* -------------------------------------------------------------------------- */ inline Real SparseMatrixAIJ::operator()(UInt i, UInt j) const { KeyCOO jcn_irn = this->key(i, j); coordinate_list_map::const_iterator irn_jcn_k_it = this->irn_jcn_k.find(jcn_irn); if (irn_jcn_k_it == this->irn_jcn_k.end()) return 0.; return this->a(irn_jcn_k_it->second); } /* -------------------------------------------------------------------------- */ inline Real & SparseMatrixAIJ::operator()(UInt i, UInt j) { KeyCOO jcn_irn = this->key(i, j); coordinate_list_map::iterator irn_jcn_k_it = this->irn_jcn_k.find(jcn_irn); AKANTU_DEBUG_ASSERT(irn_jcn_k_it != this->irn_jcn_k.end(), "Couple (i,j) = (" << i << "," << j << ") does not exist in the profile"); // it may change the profile so it is considered as a change this->value_release++; return this->a(irn_jcn_k_it->second); } -__END_AKANTU__ +} // akantu #endif /* __AKANTU_SPARSE_MATRIX_AIJ_INLINE_IMPL_CC__ */ diff --git a/src/solver/sparse_matrix_inline_impl.cc b/src/solver/sparse_matrix_inline_impl.cc index 8bce2e569..1ad017022 100644 --- a/src/solver/sparse_matrix_inline_impl.cc +++ b/src/solver/sparse_matrix_inline_impl.cc @@ -1,39 +1,39 @@ /** * @file sparse_matrix_inline_impl.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Dec 13 2010 * @date last modification: Tue Aug 18 2015 * * @brief implementation of inline methods of the SparseMatrix class * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { inline void SparseMatrix::clearProfile() { this->nb_non_zero = 0; } -__END_AKANTU__ +} // akantu diff --git a/src/solver/sparse_matrix_petsc.cc b/src/solver/sparse_matrix_petsc.cc index e6705e7c8..48456c6fb 100644 --- a/src/solver/sparse_matrix_petsc.cc +++ b/src/solver/sparse_matrix_petsc.cc @@ -1,404 +1,404 @@ /** * @file petsc_matrix.cc * @author Aurelia Cuba Ramos <aurelia.cubaramos@epfl.ch> * @date Mon Jul 21 17:40:41 2014 * * @brief Implementation of PETSc matrix 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "sparse_matrix_petsc.hh" #include "mpi_type_wrapper.hh" #include "dof_manager_petsc.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ #include <cstring> #include <petscsys.h> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { #if not defined(PETSC_CLANGUAGE_CXX) int aka_PETScError(int ierr) { CHKERRQ(ierr); return 0; } #endif /* -------------------------------------------------------------------------- */ SparseMatrixPETSc::SparseMatrixPETSc(DOFManagerPETSc & dof_manager, const MatrixType & sparse_matrix_type, const ID & id, const MemoryID & memory_id) : SparseMatrix(dof_manager, matrix_type, id, memory_id), dof_manager(dof_manager), d_nnz(0, 1, "dnnz"), o_nnz(0, 1, "onnz"), first_global_index(0) { AKANTU_DEBUG_IN(); PetscErrorCode ierr; // create the PETSc matrix object ierr = MatCreate(PETSC_COMM_WORLD, &this->mat); CHKERRXX(ierr); /** * Set the matrix type * @todo PETSc does currently not support a straightforward way to * apply Dirichlet boundary conditions for MPISBAIJ * matrices. Therefore always the entire matrix is allocated. It * would be possible to use MATSBAIJ for sequential matrices in case * memory becomes critical. Also, block matrices would give a much * better performance. Modify this in the future! */ ierr = MatSetType(this->mat, MATAIJ); CHKERRXX(ierr); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseMatrixPETSc::~SparseMatrixPETSc() { AKANTU_DEBUG_IN(); /// destroy all the PETSc data structures used for this matrix PetscErrorCode ierr; ierr = MatDestroy(&this->mat); CHKERRXX(ierr); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * With this method each processor computes the dimensions of the * local matrix, i.e. the part of the global matrix it is storing. * @param dof_synchronizer dof synchronizer that maps the local * dofs to the global dofs and the equation numbers, i.e., the * position at which the dof is assembled in the matrix */ void SparseMatrixPETSc::setSize() { AKANTU_DEBUG_IN(); // PetscErrorCode ierr; /// find the number of dofs corresponding to master or local nodes UInt nb_dofs = this->dof_manager.getLocalSystemSize(); // UInt nb_local_master_dofs = 0; /// create array to store the global equation number of all local and master /// dofs Array<Int> local_master_eq_nbs(nb_dofs); Array<Int>::scalar_iterator it_eq_nb = local_master_eq_nbs.begin(); throw; /// get the pointer to the global equation number array // Int * eq_nb_val = // this->dof_synchronizer->getGlobalDOFEquationNumbers().storage(); // for (UInt i = 0; i < nb_dofs; ++i) { // if (this->dof_synchronizer->isLocalOrMasterDOF(i)) { // *it_eq_nb = eq_nb_val[i]; // ++it_eq_nb; // ++nb_local_master_dofs; // } // } // local_master_eq_nbs.resize(nb_local_master_dofs); // /// set the local size // this->local_size = nb_local_master_dofs; // /// resize PETSc matrix // #if defined(AKANTU_USE_MPI) // ierr = MatSetSizes(this->petsc_matrix_wrapper->mat, this->local_size, // this->local_size, this->size, this->size); // CHKERRXX(ierr); // #else // ierr = MatSetSizes(this->petsc_matrix_wrapper->mat, this->local_size, // this->local_size); // CHKERRXX(ierr); // #endif // /// create mapping from akantu global numbering to petsc global numbering // this->createGlobalAkantuToPETScMap(local_master_eq_nbs.storage()); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * This method generates a mapping from the global Akantu equation * numbering to the global PETSc dof ordering * @param local_master_eq_nbs_ptr Int pointer to the array of equation * numbers of all local or master dofs, i.e. the row indices of the * local matrix */ void SparseMatrixPETSc::createGlobalAkantuToPETScMap(Int * local_master_eq_nbs_ptr) { AKANTU_DEBUG_IN(); PetscErrorCode ierr; StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); UInt rank = comm.whoAmI(); // initialize vector to store the number of local and master nodes that are // assigned to each processor Vector<UInt> master_local_ndofs_per_proc(nb_proc); /// store the nb of master and local dofs on each processor master_local_ndofs_per_proc(rank) = this->local_size; /// exchange the information among all processors comm.allGather(master_local_ndofs_per_proc.storage(), 1); /// each processor creates a map for his akantu global dofs to the /// corresponding petsc global dofs /// determine the PETSc-index for the first dof on each processor for (UInt i = 0; i < rank; ++i) { this->first_global_index += master_local_ndofs_per_proc(i); } /// create array for petsc ordering Array<Int> petsc_dofs(this->local_size); Array<Int>::scalar_iterator it_petsc_dofs = petsc_dofs.begin(); for (Int i = this->first_global_index; i < this->first_global_index + this->local_size; ++i, ++it_petsc_dofs) { *it_petsc_dofs = i; } ierr = AOCreateBasic(PETSC_COMM_WORLD, this->local_size, local_master_eq_nbs_ptr, petsc_dofs.storage(), &(this->ao)); CHKERRXX(ierr); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Method to save the nonzero pattern and the values stored at each position * @param filename name of the file in which the information will be stored */ void SparseMatrixPETSc::saveMatrix(const std::string & filename) const { AKANTU_DEBUG_IN(); PetscErrorCode ierr; /// create Petsc viewer PetscViewer viewer; ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD, filename.c_str(), &viewer); CHKERRXX(ierr); /// set the format PetscViewerSetFormat(viewer, PETSC_VIEWER_DEFAULT); CHKERRXX(ierr); /// save the matrix /// @todo Write should be done in serial -> might cause problems ierr = MatView(this->mat, viewer); CHKERRXX(ierr); /// destroy the viewer ierr = PetscViewerDestroy(&viewer); CHKERRXX(ierr); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Method to add an Akantu sparse matrix to the PETSc matrix * @param matrix Akantu sparse matrix to be added * @param alpha the factor specifying how many times the matrix should be added */ // void SparseMatrixPETSc::add(const SparseMatrix & matrix, Real alpha) { // PetscErrorCode ierr; // // AKANTU_DEBUG_ASSERT(nb_non_zero == matrix.getNbNonZero(), // // "The two matrix don't have the same profiles"); // Real val_to_add = 0; // Array<Int> index(2); // for (UInt n = 0; n < matrix.getNbNonZero(); ++n) { // UInt mat_to_add_offset = matrix.getOffset(); // index(0) = matrix.getIRN()(n) - mat_to_add_offset; // index(1) = matrix.getJCN()(n) - mat_to_add_offset; // AOApplicationToPetsc(this->petsc_matrix_wrapper->ao, 2, index.storage()); // if (this->sparse_matrix_type == _symmetric && index(0) > index(1)) // std::swap(index(0), index(1)); // val_to_add = matrix.getA()(n) * alpha; // /// MatSetValue might be very slow for MATBAIJ, might need to use // /// MatSetValuesBlocked // ierr = MatSetValue(this->petsc_matrix_wrapper->mat, index(0), index(1), // val_to_add, ADD_VALUES); // CHKERRXX(ierr); // /// chek if sparse matrix to be added is symmetric. In this case // /// the value also needs to be added at the transposed location in // /// the matrix because PETSc is using the full profile, also for symmetric // /// matrices // if (matrix.getSparseMatrixType() == _symmetric && index(0) != index(1)) // ierr = MatSetValue(this->petsc_matrix_wrapper->mat, index(1), index(0), // val_to_add, ADD_VALUES); // CHKERRXX(ierr); // } // this->performAssembly(); // } /* -------------------------------------------------------------------------- */ /** * Method to add another PETSc matrix to this PETSc matrix * @param matrix PETSc matrix to be added * @param alpha the factor specifying how many times the matrix should be added */ void SparseMatrixPETSc::add(const SparseMatrixPETSc & matrix, Real alpha) { PetscErrorCode ierr; ierr = MatAXPY(this->mat, alpha, matrix.mat, SAME_NONZERO_PATTERN); CHKERRXX(ierr); this->performAssembly(); } /* -------------------------------------------------------------------------- */ /** * MatSetValues() generally caches the values. The matrix is ready to * use only after MatAssemblyBegin() and MatAssemblyEnd() have been * called. (http://www.mcs.anl.gov/petsc/) */ void SparseMatrixPETSc::performAssembly() { this->beginAssembly(); this->endAssembly(); } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::beginAssembly() { PetscErrorCode ierr; ierr = MatAssemblyBegin(this->mat, MAT_FINAL_ASSEMBLY); CHKERRXX(ierr); ierr = MatAssemblyEnd(this->mat, MAT_FINAL_ASSEMBLY); CHKERRXX(ierr); } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::endAssembly() { PetscErrorCode ierr; ierr = MatAssemblyEnd(this->mat, MAT_FINAL_ASSEMBLY); CHKERRXX(ierr); } /* -------------------------------------------------------------------------- */ /// access K(i, j). Works only for dofs on this processor!!!! Real SparseMatrixPETSc::operator()(UInt i, UInt j) const { AKANTU_DEBUG_IN(); // AKANTU_DEBUG_ASSERT(this->dof_synchronizer->isLocalOrMasterDOF(i) && // this->dof_synchronizer->isLocalOrMasterDOF(j), // "Operator works only for dofs on this processor"); // Array<Int> index(2, 1); // index(0) = this->dof_synchronizer->getDOFGlobalID(i); // index(1) = this->dof_synchronizer->getDOFGlobalID(j); // AOApplicationToPetsc(this->petsc_matrix_wrapper->ao, 2, index.storage()); // Real value = 0; // PetscErrorCode ierr; // /// @todo MatGetValue might be very slow for MATBAIJ, might need to use // /// MatGetValuesBlocked // ierr = MatGetValues(this->petsc_matrix_wrapper->mat, 1, &index(0), 1, // &index(1), &value); // CHKERRXX(ierr); // AKANTU_DEBUG_OUT(); // return value; return 0.; } /* -------------------------------------------------------------------------- */ /** * Apply Dirichlet boundary conditions by zeroing the rows and columns which * correspond to blocked dofs * @param boundary array of booleans which are true if the dof at this position * is blocked * @param block_val the value in the diagonal entry of blocked rows */ void SparseMatrixPETSc::applyBoundary(const Array<bool> & boundary, Real block_val) { AKANTU_DEBUG_IN(); // PetscErrorCode ierr; // /// get the global equation numbers to find the rows that need to be zeroed // /// for the blocked dofs // Int * eq_nb_val = dof_synchronizer->getGlobalDOFEquationNumbers().storage(); // /// every processor calls the MatSetZero() only for his local or master dofs. // /// This assures that not two processors or more try to zero the same row // UInt nb_component = boundary.getNbComponent(); // UInt size = boundary.getSize(); // Int nb_blocked_local_master_eq_nb = 0; // Array<Int> blocked_local_master_eq_nb(this->local_size); // Int * blocked_lm_eq_nb_ptr = blocked_local_master_eq_nb.storage(); // for (UInt i = 0; i < size; ++i) { // for (UInt j = 0; j < nb_component; ++j) { // UInt local_dof = i * nb_component + j; // if (boundary(i, j) == true && // this->dof_synchronizer->isLocalOrMasterDOF(local_dof)) { // Int global_eq_nb = *eq_nb_val; // *blocked_lm_eq_nb_ptr = global_eq_nb; // ++nb_blocked_local_master_eq_nb; // ++blocked_lm_eq_nb_ptr; // } // ++eq_nb_val; // } // } // blocked_local_master_eq_nb.resize(nb_blocked_local_master_eq_nb); // ierr = AOApplicationToPetsc(this->petsc_matrix_wrapper->ao, // nb_blocked_local_master_eq_nb, // blocked_local_master_eq_nb.storage()); // CHKERRXX(ierr); // ierr = MatZeroRowsColumns( // this->petsc_matrix_wrapper->mat, nb_blocked_local_master_eq_nb, // blocked_local_master_eq_nb.storage(), block_val, 0, 0); // CHKERRXX(ierr); // this->performAssembly(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /// set all entries to zero while keeping the same nonzero pattern void SparseMatrixPETSc::clear() { MatZeroEntries(this->mat); } -__END_AKANTU__ +} // akantu diff --git a/src/solver/sparse_matrix_petsc.hh b/src/solver/sparse_matrix_petsc.hh index 68e20d25b..0fcb07f0d 100644 --- a/src/solver/sparse_matrix_petsc.hh +++ b/src/solver/sparse_matrix_petsc.hh @@ -1,142 +1,142 @@ /** * @file petsc_matrix.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Aug 21 2015 * * @brief Interface for PETSc matrices * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_PETSC_MATRIX_HH__ #define __AKANTU_PETSC_MATRIX_HH__ /* -------------------------------------------------------------------------- */ #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ #include <petscmat.h> #include <petscao.h> /* -------------------------------------------------------------------------- */ namespace akantu { class DOFManagerPETSc; } -__BEGIN_AKANTU__ +namespace akantu { class SparseMatrixPETSc : public SparseMatrix { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SparseMatrixPETSc(DOFManagerPETSc & dof_manager, const MatrixType & matrix_type, const ID & id = "sparse_matrix", const MemoryID & memory_id = 0); SparseMatrixPETSc(const SparseMatrix & matrix, const ID & id = "sparse_matrix_petsc", const MemoryID & memory_id = 0); virtual ~SparseMatrixPETSc(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// set the matrix to 0 virtual void clear(); /// modify the matrix to "remove" the blocked dof virtual void applyBoundary(const Array<bool> & boundary, Real block_val = 1.); /// save the matrix in a ASCII file format virtual void saveMatrix(const std::string & filename) const; /// add a sparse matrix assuming the profile are the same virtual void add(const SparseMatrix & matrix, Real alpha); /// add a petsc matrix assuming the profile are the same virtual void add(const SparseMatrixPETSc & matrix, Real alpha); Real operator()(UInt i, UInt j) const; protected: typedef std::pair<UInt, UInt> KeyCOO; inline KeyCOO key(UInt i, UInt j) const { return std::make_pair(i, j); } private: virtual void destroyInternalData(); /// set the size of the PETSc matrix void setSize(); void createGlobalAkantuToPETScMap(Int * local_master_eq_nbs_ptr); void createLocalAkantuToPETScMap(); /// start to assemble the matrix void beginAssembly(); /// finishes to assemble the matrix void endAssembly(); /// perform the assembly stuff from petsc void performAssembly(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(PETScMat, mat, const Mat &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: // DOFManagerPETSc that contains the numbering for petsc DOFManagerPETSc & dof_manager; /// store the PETSc matrix Mat mat; AO ao; /// size of the diagonal part of the matrix partition Int local_size; /// number of nonzeros in every row of the diagonal part Array<Int> d_nnz; /// number of nonzeros in every row of the off-diagonal part Array<Int> o_nnz; /// the global index of the first local row Int first_global_index; /// bool to indicate if the matrix data has been initialized by calling /// MatCreate bool is_petsc_matrix_initialized; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_PETSC_MATRIX_HH__ */ diff --git a/src/solver/sparse_solver.cc b/src/solver/sparse_solver.cc index 7e0ee92b1..abef9dd92 100644 --- a/src/solver/sparse_solver.cc +++ b/src/solver/sparse_solver.cc @@ -1,89 +1,89 @@ /** * @file solver.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Dec 13 2010 * @date last modification: Tue Jan 19 2016 * * @brief Solver interface class * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "mesh.hh" #include "dof_manager.hh" #include "sparse_solver.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ SparseSolver::SparseSolver(DOFManager & dof_manager, const ID & matrix_id, const ID & id, const MemoryID & memory_id) : Memory(id, memory_id), Parsable(_st_solver, id), _dof_manager(dof_manager), matrix_id(matrix_id), communicator(dof_manager.getCommunicator()) { AKANTU_DEBUG_IN(); // createSynchronizerRegistry(); // this->synch_registry = new SynchronizerRegistry(*this); // synch_registry->registerSynchronizer(this->matrix->getDOFSynchronizer(), // _gst_solver_solution); // OK this is fishy... const_cast<StaticCommunicator &>(this->communicator).registerEventHandler(*this); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseSolver::~SparseSolver() { AKANTU_DEBUG_IN(); this->destroyInternalData(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseSolver::beforeStaticSolverDestroy() { AKANTU_DEBUG_IN(); try { this->destroyInternalData(); } catch (...) { } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseSolver::createSynchronizerRegistry() { // this->synch_registry = new SynchronizerRegistry(this); } void SparseSolver::onCommunicatorFinalize() { this->destroyInternalData(); } -__END_AKANTU__ +} // akantu diff --git a/src/solver/sparse_solver.hh b/src/solver/sparse_solver.hh index acd0ad49d..40eee3664 100644 --- a/src/solver/sparse_solver.hh +++ b/src/solver/sparse_solver.hh @@ -1,122 +1,122 @@ /** * @file sparse_solver.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Jan 19 2016 * * @brief interface for solvers * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" //#include "data_accessor.hh" #include "parsable.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLVER_HH__ #define __AKANTU_SOLVER_HH__ namespace akantu { enum SolverParallelMethod { _not_parallel, _fully_distributed, _master_slave_distributed }; class DOFManager; } -__BEGIN_AKANTU__ +namespace akantu { class SparseSolver : protected Memory, public Parsable, public CommunicatorEventHandler { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SparseSolver(DOFManager & dof_manager, const ID & matrix_id, const ID & id = "solver", const MemoryID & memory_id = 0); virtual ~SparseSolver(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the solver virtual void initialize() = 0; virtual void analysis(){}; virtual void factorize(){}; virtual void solve(){}; protected: virtual void destroyInternalData(){}; public: virtual void beforeStaticSolverDestroy(); void createSynchronizerRegistry(); /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ public: virtual void onCommunicatorFinalize(); // inline virtual UInt getNbDataForDOFs(const Array<UInt> & dofs, // SynchronizationTag tag) const; // inline virtual void packDOFData(CommunicationBuffer & buffer, // const Array<UInt> & dofs, // SynchronizationTag tag) const; // inline virtual void unpackDOFData(CommunicationBuffer & buffer, // const Array<UInt> & dofs, // SynchronizationTag tag); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// manager handling the dofs for this SparseMatrix solver DOFManager & _dof_manager; /// The id of the associated matrix ID matrix_id; /// How to parallelize the solve SolverParallelMethod parallel_method; /// Communicator used by the solver const StaticCommunicator & communicator; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_SOLVER_HH__ */ diff --git a/src/solver/sparse_solver_mumps.cc b/src/solver/sparse_solver_mumps.cc index 8fa28517c..54786d40a 100644 --- a/src/solver/sparse_solver_mumps.cc +++ b/src/solver/sparse_solver_mumps.cc @@ -1,441 +1,441 @@ /** * @file sparse_solver_mumps.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Dec 13 2010 * @date last modification: Tue Jan 19 2016 * * @brief implem of SparseSolverMumps class * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * * @section DESCRIPTION * * @subsection Ctrl_param Control parameters * * ICNTL(1), * ICNTL(2), * ICNTL(3) : output streams for error, diagnostics, and global messages * * ICNTL(4) : verbose level : 0 no message - 4 all messages * * ICNTL(5) : type of matrix, 0 assembled, 1 elementary * * ICNTL(6) : control the permutation and scaling(default 7) see mumps doc for * more information * * ICNTL(7) : determine the pivot order (default 7) see mumps doc for more * information * * ICNTL(8) : describe the scaling method used * * ICNTL(9) : 1 solve A x = b, 0 solve At x = b * * ICNTL(10) : number of iterative refinement when NRHS = 1 * * ICNTL(11) : > 0 return statistics * * ICNTL(12) : only used for SYM = 2, ordering strategy * * ICNTL(13) : * * ICNTL(14) : percentage of increase of the estimated working space * * ICNTL(15-17) : not used * * ICNTL(18) : only used if ICNTL(5) = 0, 0 matrix centralized, 1 structure on * host and mumps give the mapping, 2 structure on host and distributed matrix * for facto, 3 distributed matrix * * ICNTL(19) : > 0, Shur complement returned * * ICNTL(20) : 0 rhs dense, 1 rhs sparse * * ICNTL(21) : 0 solution in rhs, 1 solution distributed in ISOL_loc and SOL_loc * allocated by user * * ICNTL(22) : 0 in-core, 1 out-of-core * * ICNTL(23) : maximum memory allocatable by mumps pre proc * * ICNTL(24) : controls the detection of "null pivot rows" * * ICNTL(25) : * * ICNTL(26) : * * ICNTL(27) : * * ICNTL(28) : 0 automatic choice, 1 sequential analysis, 2 parallel analysis * * ICNTL(29) : 0 automatic choice, 1 PT-Scotch, 2 ParMetis */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "dof_manager_default.hh" #include "dof_synchronizer.hh" #include "sparse_matrix_aij.hh" #if defined(AKANTU_USE_MPI) #include "mpi_type_wrapper.hh" #include "static_communicator_mpi.hh" #endif #include "sparse_solver_mumps.hh" /* -------------------------------------------------------------------------- */ // static std::ostream & operator <<(std::ostream & stream, const DMUMPS_STRUC_C // & _this) { // stream << "DMUMPS Data [" << std::endl; // stream << " + job : " << _this.job << std::endl; // stream << " + par : " << _this.par << std::endl; // stream << " + sym : " << _this.sym << std::endl; // stream << " + comm_fortran : " << _this.comm_fortran << std::endl; // stream << " + nz : " << _this.nz << std::endl; // stream << " + irn : " << _this.irn << std::endl; // stream << " + jcn : " << _this.jcn << std::endl; // stream << " + nz_loc : " << _this.nz_loc << std::endl; // stream << " + irn_loc : " << _this.irn_loc << std::endl; // stream << " + jcn_loc : " << _this.jcn_loc << std::endl; // stream << "]"; // return stream; // } -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ SparseSolverMumps::SparseSolverMumps(DOFManagerDefault & dof_manager, const ID & matrix_id, const ID & id, const MemoryID & memory_id) : SparseSolver(dof_manager, matrix_id, id, memory_id), dof_manager(dof_manager), matrix(dof_manager.getMatrix(matrix_id)), master_rhs_solution(0, 1), is_initialized(false) { AKANTU_DEBUG_IN(); this->prank = communicator.whoAmI(); #ifdef AKANTU_USE_MPI this->parallel_method = _fully_distributed; #else // AKANTU_USE_MPI this->parallel_method = _not_parallel; #endif // AKANTU_USE_MPI this->mumps_data.par = 1; // The host is part of computations switch (this->parallel_method) { case _not_parallel: break; case _master_slave_distributed: this->mumps_data.par = 0; // The host is not part of the computations case _fully_distributed: #ifdef AKANTU_USE_MPI const StaticCommunicatorMPI & mpi_st_comm = dynamic_cast<const StaticCommunicatorMPI &>( communicator.getRealStaticCommunicator()); MPI_Comm mpi_comm = mpi_st_comm.getMPITypeWrapper().getMPICommunicator(); this->mumps_data.comm_fortran = MPI_Comm_c2f(mpi_comm); #else AKANTU_DEBUG_ERROR( "You cannot use parallel method to solve without activating MPI"); #endif break; } this->mumps_data.sym = 2 * (this->matrix.getMatrixType() == _symmetric); this->prank = communicator.whoAmI(); this->setOutputLevel(); this->mumps_data.job = _smj_initialize; // initialize dmumps_c(&this->mumps_data); this->setOutputLevel(); this->is_initialized = true; this->last_profile_release = this->matrix.getProfileRelease() - 1; this->last_value_release = this->matrix.getValueRelease() - 1; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseSolverMumps::~SparseSolverMumps() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::destroyInternalData() { if (this->is_initialized) { this->mumps_data.job = _smj_destroy; // destroy dmumps_c(&this->mumps_data); this->is_initialized = false; } } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::checkInitialized() { if (!this->is_initialized) AKANTU_EXCEPTION("You cannot use an un/de-initialized mumps solver"); } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::setOutputLevel() { // Output setup icntl(1) = 0; // error output icntl(2) = 0; // dignostics output icntl(3) = 0; // informations icntl(4) = 0; #if !defined(AKANTU_NDEBUG) DebugLevel dbg_lvl = debug::debugger.getDebugLevel(); if (AKANTU_DEBUG_TEST(dblDump)) { strcpy(this->mumps_data.write_problem, "mumps_matrix.mtx"); } icntl(1) = (dbg_lvl >= dblWarning) ? 6 : 0; icntl(3) = (dbg_lvl >= dblInfo) ? 6 : 0; icntl(2) = (dbg_lvl >= dblTrace) ? 6 : 0; if (dbg_lvl >= dblDump) { icntl(4) = 4; } else if (dbg_lvl >= dblTrace) { icntl(4) = 3; } else if (dbg_lvl >= dblInfo) { icntl(4) = 2; } else if (dbg_lvl >= dblWarning) { icntl(4) = 1; } #endif } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::initMumpsData() { // Default Scaling icntl(8) = 77; // Assembled matrix icntl(5) = 0; /// Default centralized dense second member icntl(20) = 0; icntl(21) = 0; // automatic choice for analysis icntl(28) = 0; UInt size = this->matrix.getSize(); if (prank == 0) { this->master_rhs_solution.resize(size); } this->mumps_data.nz_alloc = 0; this->mumps_data.n = size; switch (this->parallel_method) { case _fully_distributed: icntl(18) = 3; // fully distributed this->mumps_data.nz_loc = matrix.getNbNonZero(); this->mumps_data.irn_loc = matrix.getIRN().storage(); this->mumps_data.jcn_loc = matrix.getJCN().storage(); break; case _not_parallel: case _master_slave_distributed: icntl(18) = 0; // centralized if (prank == 0) { this->mumps_data.nz = matrix.getNbNonZero(); this->mumps_data.irn = matrix.getIRN().storage(); this->mumps_data.jcn = matrix.getJCN().storage(); } else { this->mumps_data.nz = 0; this->mumps_data.irn = NULL; this->mumps_data.jcn = NULL; } break; default: AKANTU_DEBUG_ERROR("This case should not happen!!"); } } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::initialize() { AKANTU_DEBUG_IN(); this->analysis(); // icntl(14) = 80; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::analysis() { AKANTU_DEBUG_IN(); initMumpsData(); this->checkInitialized(); this->mumps_data.job = _smj_analyze; // analyze dmumps_c(&this->mumps_data); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::factorize() { AKANTU_DEBUG_IN(); // should be null on slaves // this->mumps_data.rhs = this->master_rhs_solution.storage(); if (parallel_method == _fully_distributed) this->mumps_data.a_loc = this->matrix.getA().storage(); else { if (prank == 0) this->mumps_data.a = this->matrix.getA().storage(); } this->checkInitialized(); this->mumps_data.job = _smj_factorize; // factorize dmumps_c(&this->mumps_data); this->printError(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::solve(Array<Real> & x, const Array<Real> & b) { auto & synch = this->dof_manager.getSynchronizer(); if (this->prank == 0) { this->master_rhs_solution.resize(this->dof_manager.getSystemSize()); synch.gather(b, this->master_rhs_solution); } else { synch.gather(b); } this->solveInternal(); if (this->prank == 0) { synch.scatter(x, this->master_rhs_solution); } else { synch.scatter(x); } } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::solve() { this->master_rhs_solution.copy(this->dof_manager.getGlobalResidual()); this->solveInternal(); this->dof_manager.setGlobalSolution(this->master_rhs_solution); this->dof_manager.splitSolutionPerDOFs(); } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::solveInternal() { AKANTU_DEBUG_IN(); this->setOutputLevel(); if (this->last_profile_release != this->matrix.getProfileRelease()) { this->analysis(); this->last_profile_release = this->matrix.getProfileRelease(); } if (AKANTU_DEBUG_TEST(dblDump)) { std::stringstream sstr; sstr << prank << ".mtx"; this->matrix.saveMatrix("solver_mumps" + sstr.str()); } if (this->last_value_release != this->matrix.getValueRelease()) { this->factorize(); this->last_value_release = this->matrix.getValueRelease(); } if (prank == 0) { this->mumps_data.rhs = this->master_rhs_solution.storage(); } this->checkInitialized(); this->mumps_data.job = _smj_solve; // solve dmumps_c(&this->mumps_data); this->printError(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::printError() { Vector<Int> _info_v(2); _info_v[0] = info(1); // to get errors _info_v[1] = -info(1); // to get warnings StaticCommunicator::getStaticCommunicator().allReduce(_info_v, _so_min); _info_v[1] = -_info_v[1]; if (_info_v[0] < 0) { // < 0 is an error switch (_info_v[0]) { case -10: AKANTU_DEBUG_ERROR("The matrix is singular"); break; case -9: { icntl(14) += 10; if (icntl(14) != 90) { // std::cout << "Dynamic memory increase of 10%" << std::endl; AKANTU_DEBUG_WARNING("MUMPS dynamic memory is insufficient it will be " "increased allowed to use 10% more"); // change releases to force a recompute this->last_value_release--; this->last_profile_release--; this->solve(); } else { AKANTU_DEBUG_ERROR("The MUMPS workarray is too small INFO(2)=" << info(2) << "No further increase possible"); break; } } default: AKANTU_DEBUG_ERROR("Error in mumps during solve process, check mumps " "user guide INFO(1) = " << _info_v[1]); } } else if (_info_v[1] > 0) { AKANTU_DEBUG_WARNING("Warning in mumps during solve process, check mumps " "user guide INFO(1) = " << _info_v[1]); } } -__END_AKANTU__ +} // akantu diff --git a/src/solver/sparse_solver_mumps.hh b/src/solver/sparse_solver_mumps.hh index b30b0e8dc..43d412235 100644 --- a/src/solver/sparse_solver_mumps.hh +++ b/src/solver/sparse_solver_mumps.hh @@ -1,160 +1,160 @@ /** * @file sparse_solver_mumps.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Jan 19 2016 * * @brief Solver class implementation for the mumps solver * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "sparse_solver.hh" /* -------------------------------------------------------------------------- */ #include <dmumps_c.h> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLVER_MUMPS_HH__ #define __AKANTU_SOLVER_MUMPS_HH__ namespace akantu { class DOFManagerDefault; class SparseMatrixAIJ; } -__BEGIN_AKANTU__ +namespace akantu { class SparseSolverMumps : public SparseSolver { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SparseSolverMumps(DOFManagerDefault & dof_manager, const ID & matrix_id, const ID & id = "sparse_solver_mumps", const MemoryID & memory_id = 0); virtual ~SparseSolverMumps(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// build the profile and do the analysis part virtual void initialize(); /// analysis (symbolic facto + permutations) virtual void analysis(); /// factorize the matrix virtual void factorize(); /// solve the system virtual void solve(Array<Real> & x, const Array<Real> & b); /// solve using residual and solution from the dof_manager virtual void solve(); private: /// print the error if any happened in mumps void printError(); /// solve the system with master_rhs_solution as b and x void solveInternal(); /// set internal values; void initMumpsData(); /// set the level of verbosity of mumps based on the debug level of akantu void setOutputLevel(); protected: /// de-initialize the internal data virtual void destroyInternalData(); /// check if initialized and except if it is not the case void checkInitialized(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ private: /// access the control variable inline Int & icntl(UInt i) { return mumps_data.icntl[i - 1]; } /// access the results info inline Int & info(UInt i) { return mumps_data.info[i - 1]; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// DOFManager used by the Mumps implementation of the SparseSolver DOFManagerDefault & dof_manager; /// AIJ Matrix, usualy the jacobian matrix SparseMatrixAIJ & matrix; /// Full right hand side on the master processors and solution after solve Array<Real> master_rhs_solution; /// mumps data DMUMPS_STRUC_C mumps_data; /// Rank of the current process UInt prank; /// matrix release at last solve UInt last_profile_release; /// matrix release at last solve UInt last_value_release; /// check if the solver data are initialized bool is_initialized; /* ------------------------------------------------------------------------ */ /* Local types */ /* ------------------------------------------------------------------------ */ private: SolverParallelMethod parallel_method; // bool rhs_is_local; enum SolverMumpsJob { _smj_initialize = -1, _smj_analyze = 1, _smj_factorize = 2, _smj_solve = 3, _smj_analyze_factorize = 4, _smj_factorize_solve = 5, _smj_complete = 6, // analyze, factorize, solve _smj_destroy = -2 }; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_SOLVER_MUMPS_HH__ */ diff --git a/src/synchronizer/communication_buffer.hh b/src/synchronizer/communication_buffer.hh index 1a10d2467..b98bde035 100644 --- a/src/synchronizer/communication_buffer.hh +++ b/src/synchronizer/communication_buffer.hh @@ -1,193 +1,193 @@ /** * @file communication_buffer.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Oct 19 2014 * * @brief Buffer for packing and unpacking data * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_array.hh" #include "element.hh" #ifndef __AKANTU_COMMUNICATION_BUFFER_HH__ #define __AKANTU_COMMUNICATION_BUFFER_HH__ -__BEGIN_AKANTU__ +namespace akantu { template<bool is_static = true> class CommunicationBufferTemplated { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: explicit CommunicationBufferTemplated(UInt size) : buffer(size, 1) { ptr_pack = buffer.storage(); ptr_unpack = buffer.storage(); }; CommunicationBufferTemplated() : CommunicationBufferTemplated(0) {} CommunicationBufferTemplated(const CommunicationBufferTemplated & other) { buffer = other.buffer; ptr_pack = buffer.storage(); ptr_unpack = buffer.storage(); } CommunicationBufferTemplated & operator=(const CommunicationBufferTemplated & other) { if (this != &other) { buffer = other.buffer; ptr_pack = buffer.storage(); ptr_unpack = buffer.storage(); } return *this; } virtual ~CommunicationBufferTemplated() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// reset to "empty" inline void reset(); /// resize the internal buffer inline void resize(UInt size); /// clear buffer context inline void clear(); private: inline void packResize(UInt size); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: inline char * storage() { return buffer.storage(); }; /* ------------------------------------------------------------------------ */ /* Operators */ /* ------------------------------------------------------------------------ */ public: /// printing tool template <typename T> inline std::string extractStream(UInt packet_size); /// packing data template<typename T> inline CommunicationBufferTemplated & operator<< (const T & to_pack); template<typename T> inline CommunicationBufferTemplated & operator<< (const Vector<T> & to_pack); template<typename T> inline CommunicationBufferTemplated & operator<< (const Matrix<T> & to_pack); template<typename T> inline CommunicationBufferTemplated & operator<< (const std::vector<T> & to_pack); /// unpacking data template<typename T> inline CommunicationBufferTemplated & operator>> (T & to_unpack); template<typename T> inline CommunicationBufferTemplated & operator>> (Vector<T> & to_unpack); template<typename T> inline CommunicationBufferTemplated & operator>> (Matrix<T> & to_unpack); template<typename T> inline CommunicationBufferTemplated & operator>> (std::vector<T> & to_unpack); inline CommunicationBufferTemplated & operator<< (const std::string & to_pack); inline CommunicationBufferTemplated & operator>> (std::string & to_unpack); private: template<typename T> inline void packIterable (T & to_pack); template<typename T> inline void unpackIterable (T & to_pack); /* ------------------------------------------------------------------------ */ /* Accessor */ /* ------------------------------------------------------------------------ */ public: template <typename T> static inline UInt sizeInBuffer(const T & data); template <typename T> static inline UInt sizeInBuffer(const Vector<T> & data); template <typename T> static inline UInt sizeInBuffer(const Matrix<T> & data); template <typename T> static inline UInt sizeInBuffer(const std::vector<T> & data); static inline UInt sizeInBuffer(const std::string & data); /// return the size in bytes of the stored values inline UInt getPackedSize(){ return ptr_pack - buffer.storage(); }; /// return the size in bytes of data left to be unpacked inline UInt getLeftToUnpack(){ return buffer.getSize() - (ptr_unpack - buffer.storage()); }; /// return the global size allocated inline UInt getSize(){ return buffer.getSize(); }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// current position for packing char * ptr_pack; /// current position for unpacking char * ptr_unpack; /// storing buffer Array<char> buffer; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "communication_buffer_inline_impl.cc" #endif typedef CommunicationBufferTemplated<true> CommunicationBuffer; typedef CommunicationBufferTemplated<false> DynamicCommunicationBuffer; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_COMMUNICATION_BUFFER_HH__ */ diff --git a/src/synchronizer/dof_synchronizer.cc b/src/synchronizer/dof_synchronizer.cc index 2bc478a4c..22a0c9d13 100644 --- a/src/synchronizer/dof_synchronizer.cc +++ b/src/synchronizer/dof_synchronizer.cc @@ -1,220 +1,220 @@ /** * @file dof_synchronizer.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 17 2011 * @date last modification: Wed Oct 21 2015 * * @brief DOF synchronizing object implementation * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "dof_synchronizer.hh" #include "dof_manager_default.hh" #include "mesh.hh" #include "node_synchronizer.hh" /* -------------------------------------------------------------------------- */ #include <algorithm> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ /** * A DOFSynchronizer needs a mesh and the number of degrees of freedom * per node to be created. In the constructor computes the local and global dof * number for each dof. The member * proc_informations (std vector) is resized with the number of mpi * processes. Each entry in the vector is a PerProcInformations object * that contains the interactions of the current mpi process (prank) with the * mpi process corresponding to the position of that entry. Every * ProcInformations object contains one array with the dofs that have * to be sent to prank and a second one with dofs that willl be received form * prank. * This information is needed for the asychronous communications. The * constructor sets up this information. */ DOFSynchronizer::DOFSynchronizer(DOFManagerDefault & dof_manager, const ID & id, MemoryID memory_id, const StaticCommunicator & comm) : SynchronizerImpl<UInt>(id, memory_id, comm), root(0), dof_manager(dof_manager), root_dofs(0, 1, "dofs-to-receive-from-master"), dof_changed(true) { std::vector<ID> dof_ids = dof_manager.getDOFIDs(); // Transfers nodes to global equation numbers in new schemes for (ID dof_id : dof_ids) { registerDOFs(dof_id); } this->initScatterGatherCommunicationScheme(); } /* -------------------------------------------------------------------------- */ DOFSynchronizer::~DOFSynchronizer() {} /* -------------------------------------------------------------------------- */ void DOFSynchronizer::registerDOFs(const ID & dof_id) { if (this->nb_proc == 1) return; typedef Communications<UInt>::const_scheme_iterator const_scheme_iterator; const Array<UInt> equation_numbers = dof_manager.getLocalEquationNumbers(dof_id); if (dof_manager.getSupportType(dof_id) == _dst_nodal) { const NodeSynchronizer & node_synchronizer = dof_manager.getMesh().getNodeSynchronizer(); const Array<UInt> & associated_nodes = dof_manager.getDOFsAssociatedNodes(dof_id); const Communications<UInt> & node_communications = node_synchronizer.getCommunications(); auto transcode_node_to_global_dof_scheme = [this, &associated_nodes, &equation_numbers](const_scheme_iterator it, const_scheme_iterator end, const CommunicationSendRecv & sr) -> void { for (; it != end; ++it) { auto & scheme = communications.createScheme(it->first, sr); const auto & node_scheme = it->second; for (auto & node : node_scheme) { auto an_begin = associated_nodes.begin(); auto an_it = an_begin; auto an_end = associated_nodes.end(); std::vector<UInt> global_dofs_per_node; while ((an_it = std::find(an_it, an_end, node)) != an_end) { UInt pos = an_it - an_begin; UInt local_eq_num = equation_numbers(pos); UInt global_eq_num = dof_manager.localToGlobalEquationNumber(local_eq_num); global_dofs_per_node.push_back(global_eq_num); ++an_it; } std::sort(global_dofs_per_node.begin(), global_dofs_per_node.end()); std::transform(global_dofs_per_node.begin(), global_dofs_per_node.end(), global_dofs_per_node.begin(), [this](UInt g) -> UInt { UInt l = dof_manager.globalToLocalEquationNumber(g); return l; }); for (auto & leqnum : global_dofs_per_node) { scheme.push_back(leqnum); } } } }; auto nss_it = node_communications.begin_send_scheme(); auto nss_end = node_communications.end_send_scheme(); transcode_node_to_global_dof_scheme(nss_it, nss_end, _send); auto nrs_it = node_communications.begin_recv_scheme(); auto nrs_end = node_communications.end_recv_scheme(); transcode_node_to_global_dof_scheme(nrs_it, nrs_end, _recv); } dof_changed = true; } /* -------------------------------------------------------------------------- */ void DOFSynchronizer::initScatterGatherCommunicationScheme() { AKANTU_DEBUG_IN(); if (this->nb_proc == 1) { dof_changed = false; AKANTU_DEBUG_OUT(); return; } UInt nb_dofs = dof_manager.getLocalSystemSize(); this->root_dofs.clear(); this->master_receive_dofs.clear(); Array<UInt> dofs_to_send; for (UInt n = 0; n < nb_dofs; ++n) { if (dof_manager.isLocalOrMasterDOF(n)) { auto & receive_per_proc = master_receive_dofs[this->root]; UInt global_dof = dof_manager.localToGlobalEquationNumber(n); root_dofs.push_back(n); receive_per_proc.push_back(global_dof); dofs_to_send.push_back(global_dof); } } if (this->rank == UInt(this->root)) { Array<UInt> nb_dof_per_proc(this->nb_proc); communicator.gather(dofs_to_send.getSize(), nb_dof_per_proc); std::vector<CommunicationRequest> requests; for (UInt p = 0; p < nb_proc; ++p) { if (p == UInt(this->root)) continue; auto & receive_per_proc = master_receive_dofs[p]; receive_per_proc.resize(nb_dof_per_proc(p)); if (nb_dof_per_proc(p) != 0) requests.push_back(communicator.asyncReceive( receive_per_proc, p, Tag::genTag(p, 0, Tag::_GATHER_INITIALIZATION, this->hash_id))); } communicator.waitAll(requests); communicator.freeCommunicationRequest(requests); } else { communicator.gather(dofs_to_send.getSize(), this->root); AKANTU_DEBUG(dblDebug, "I have " << nb_dofs << " dofs (" << dofs_to_send.getSize() << " to send to master proc"); if (dofs_to_send.getSize() != 0) communicator.send(dofs_to_send, this->root, Tag::genTag(this->rank, 0, Tag::_GATHER_INITIALIZATION, this->hash_id)); } dof_changed = false; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool DOFSynchronizer::hasChanged() { communicator.allReduce(dof_changed, _so_lor); return dof_changed; } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/synchronizer/element_info_per_processor.cc b/src/synchronizer/element_info_per_processor.cc index 49e4e86f4..5bbaffe58 100644 --- a/src/synchronizer/element_info_per_processor.cc +++ b/src/synchronizer/element_info_per_processor.cc @@ -1,111 +1,111 @@ /** * @file element_info_per_processor.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Fri Mar 11 14:56:42 2016 * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "element_info_per_processor.hh" #include "element_synchronizer.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ #include <algorithm> #include <iostream> #include <map> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ ElementInfoPerProc::ElementInfoPerProc(ElementSynchronizer & synchronizer, UInt message_cnt, UInt root, ElementType type) : MeshAccessor(synchronizer.getMesh()), synchronizer(synchronizer), rank(synchronizer.getCommunicator().whoAmI()), nb_proc(synchronizer.getCommunicator().getNbProc()), root(root), type(type), message_count(message_cnt), mesh(synchronizer.getMesh()), comm(synchronizer.getCommunicator()) { } /* -------------------------------------------------------------------------- */ void ElementInfoPerProc::fillCommunicationScheme( const Array<UInt> & partition) { AKANTU_DEBUG_IN(); Element element; element.type = this->type; element.kind = Mesh::getKind(this->type); Communications<Element> & communications = this->synchronizer.getCommunications(); Array<UInt>::const_scalar_iterator part = partition.begin(); std::map<UInt, Array<Element> > send_array_per_proc; for (UInt lel = 0; lel < nb_local_element; ++lel) { UInt nb_send = *part; ++part; element.element = lel; element.ghost_type = _not_ghost; for (UInt p = 0; p < nb_send; ++p, ++part) { UInt proc = *part; AKANTU_DEBUG(dblAccessory, "Must send : " << element << " to proc " << proc); send_array_per_proc[proc].push_back(element); } } for (auto & send_schemes : send_array_per_proc) { if (send_schemes.second.getSize() == 0) continue; auto & scheme = communications.createSendScheme(send_schemes.first); scheme.append(send_schemes.second); } std::map<UInt, Array<Element> > recv_array_per_proc; for (UInt gel = 0; gel < nb_ghost_element; ++gel, ++part) { UInt proc = *part; element.element = gel; element.ghost_type = _ghost; AKANTU_DEBUG(dblAccessory, "Must recv : " << element << " from proc " << proc); recv_array_per_proc[proc].push_back(element); } for (auto & recv_schemes : recv_array_per_proc) { if (recv_schemes.second.getSize() == 0) continue; auto & scheme = communications.createRecvScheme(recv_schemes.first); scheme.append(recv_schemes.second); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/synchronizer/element_info_per_processor.hh b/src/synchronizer/element_info_per_processor.hh index 7be591ea0..88ce97160 100644 --- a/src/synchronizer/element_info_per_processor.hh +++ b/src/synchronizer/element_info_per_processor.hh @@ -1,144 +1,144 @@ /** * @file element_info_per_processor.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Fri Mar 11 14:45:15 2016 * * @brief Helper classes to create the distributed synchronizer and distribute * 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "communication_buffer.hh" #include "mesh.hh" #include "mesh_accessor.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ELEMENT_INFO_PER_PROCESSOR_HH__ #define __AKANTU_ELEMENT_INFO_PER_PROCESSOR_HH__ namespace akantu { class ElementSynchronizer; class StaticCommunicator; class MeshPartition; } /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class ElementInfoPerProc : protected MeshAccessor { public: ElementInfoPerProc(ElementSynchronizer & synchronizer, UInt message_cnt, UInt root, ElementType type); virtual void synchronizeConnectivities() = 0; virtual void synchronizePartitions() = 0; virtual void synchronizeTags() = 0; virtual void synchronizeGroups() = 0; protected: void fillCommunicationScheme(const Array<UInt> & partition); template <class CommunicationBuffer> void fillElementGroupsFromBuffer(CommunicationBuffer & buffer); template <typename T, typename BufferType> void fillMeshDataTemplated(BufferType & buffer, const std::string & tag_name, UInt nb_component); template <typename BufferType> void fillMeshData(BufferType & buffer, const std::string & tag_name, const MeshDataTypeCode & type_code, UInt nb_component); protected: ElementSynchronizer & synchronizer; UInt rank; UInt nb_proc; UInt root; ElementType type; UInt nb_tags; UInt nb_nodes_per_element; UInt nb_element; UInt nb_local_element; UInt nb_ghost_element; UInt message_count; Mesh & mesh; const StaticCommunicator & comm; }; /* -------------------------------------------------------------------------- */ class MasterElementInfoPerProc : protected ElementInfoPerProc { public: MasterElementInfoPerProc(ElementSynchronizer & synchronizer, UInt message_cnt, UInt root, ElementType type, const MeshPartition & partition); void synchronizeConnectivities(); void synchronizePartitions(); void synchronizeTags(); void synchronizeGroups(); protected: template <typename T> void fillTagBufferTemplated(DynamicCommunicationBuffer * buffers, const std::string & tag_name); void fillTagBuffer(DynamicCommunicationBuffer * buffers, const std::string & tag_name); private: const MeshPartition & partition; Vector<UInt> all_nb_local_element; Vector<UInt> all_nb_ghost_element; Vector<UInt> all_nb_element_to_send; }; /* -------------------------------------------------------------------------- */ class SlaveElementInfoPerProc : protected ElementInfoPerProc { public: SlaveElementInfoPerProc(ElementSynchronizer & synchronizer, UInt message_cnt, UInt root); void synchronizeConnectivities(); void synchronizePartitions(); void synchronizeTags(); void synchronizeGroups(); bool needSynchronize(); private: UInt nb_element_to_receive; }; -__END_AKANTU__ +} // akantu #include "element_info_per_processor_tmpl.hh" #endif /* __AKANTU_ELEMENT_INFO_PER_PROCESSOR_HH__ */ diff --git a/src/synchronizer/element_info_per_processor_tmpl.hh b/src/synchronizer/element_info_per_processor_tmpl.hh index d47ae74f4..20390c680 100644 --- a/src/synchronizer/element_info_per_processor_tmpl.hh +++ b/src/synchronizer/element_info_per_processor_tmpl.hh @@ -1,149 +1,149 @@ /** * @file element_info_per_processor_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Fri Mar 11 15:03:12 2016 * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "element_group.hh" #include "element_info_per_processor.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ELEMENT_INFO_PER_PROCESSOR_TMPL_HH__ #define __AKANTU_ELEMENT_INFO_PER_PROCESSOR_TMPL_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ template <typename T, typename BufferType> void ElementInfoPerProc::fillMeshDataTemplated(BufferType & buffer, const std::string & tag_name, UInt nb_component) { AKANTU_DEBUG_ASSERT(this->mesh.getNbElement(this->type) == nb_local_element, "Did not got enought informations for the tag " << tag_name << " and the element type " << this->type << ":" << "_not_ghost." << " Got " << nb_local_element << " values, expected " << mesh.getNbElement(this->type)); MeshData & mesh_data = this->getMeshData(); mesh_data.registerElementalData<T>(tag_name); Array<T> & data = mesh_data.getElementalDataArrayAlloc<T>( tag_name, this->type, _not_ghost, nb_component); data.resize(nb_local_element); /// unpacking the data, element by element for (UInt i(0); i < nb_local_element; ++i) { for (UInt j(0); j < nb_component; ++j) { buffer >> data(i, j); } } AKANTU_DEBUG_ASSERT(mesh.getNbElement(this->type, _ghost) == nb_ghost_element, "Did not got enought informations for the tag " << tag_name << " and the element type " << this->type << ":" << "_ghost." << " Got " << nb_ghost_element << " values, expected " << mesh.getNbElement(this->type, _ghost)); Array<T> & data_ghost = mesh_data.getElementalDataArrayAlloc<T>( tag_name, this->type, _ghost, nb_component); data_ghost.resize(nb_ghost_element); /// unpacking the ghost data, element by element for (UInt j(0); j < nb_ghost_element; ++j) { for (UInt k(0); k < nb_component; ++k) { buffer >> data_ghost(j, k); } } } /* -------------------------------------------------------------------------- */ template <typename BufferType> void ElementInfoPerProc::fillMeshData(BufferType & buffer, const std::string & tag_name, const MeshDataTypeCode & type_code, UInt nb_component) { #define AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA(r, extra_param, elem) \ case BOOST_PP_TUPLE_ELEM(2, 0, elem): { \ fillMeshDataTemplated<BOOST_PP_TUPLE_ELEM(2, 1, elem)>(buffer, tag_name, \ nb_component); \ break; \ } switch (type_code) { BOOST_PP_SEQ_FOR_EACH(AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA, , AKANTU_MESH_DATA_TYPES) default: AKANTU_DEBUG_ERROR("Could not determine the type of tag" << tag_name << "!"); break; } #undef AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA } /* -------------------------------------------------------------------------- */ template <class CommunicationBuffer> void ElementInfoPerProc::fillElementGroupsFromBuffer( CommunicationBuffer & buffer) { AKANTU_DEBUG_IN(); Element el; el.type = type; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { UInt nb_element = mesh.getNbElement(type, *gt); el.ghost_type = *gt; for (UInt e = 0; e < nb_element; ++e) { el.element = e; std::vector<std::string> element_to_group; buffer >> element_to_group; AKANTU_DEBUG_ASSERT(e < mesh.getNbElement(type, *gt), "The mesh does not have the element " << e); std::vector<std::string>::iterator it = element_to_group.begin(); std::vector<std::string>::iterator end = element_to_group.end(); for (; it != end; ++it) { mesh.getElementGroup(*it).add(el, false, false); } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu #endif /* __AKANTU_ELEMENT_INFO_PER_PROCESSOR_TMPL_HH__ */ diff --git a/src/synchronizer/filtered_synchronizer.cc b/src/synchronizer/filtered_synchronizer.cc index a48038869..e61910d00 100644 --- a/src/synchronizer/filtered_synchronizer.cc +++ b/src/synchronizer/filtered_synchronizer.cc @@ -1,174 +1,174 @@ /** * @file filtered_synchronizer.cc * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Mathilde Radiguet <mathilde.radiguet@epfl.ch> * * @date creation: Wed Sep 18 2013 * @date last modification: Sat Jul 11 2015 * * @brief filtered synchronizer * * @section LICENSE * * Copyright (©) 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "filtered_synchronizer.hh" /* -------------------------------------------------------------------------- */ #include <map> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ FilteredSynchronizer::FilteredSynchronizer(Mesh & mesh, SynchronizerID id, MemoryID memory_id) : ElementSynchronizer(mesh, id, memory_id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ FilteredSynchronizer * FilteredSynchronizer::createFilteredSynchronizer( const ElementSynchronizer & d_synchronizer, SynchElementFilter & filter) { AKANTU_DEBUG_IN(); FilteredSynchronizer & f_synchronizer = *(new FilteredSynchronizer( d_synchronizer.mesh, d_synchronizer.id + ":filtered", d_synchronizer.memory_id)); f_synchronizer.setupSynchronizer(d_synchronizer, filter); AKANTU_DEBUG_OUT(); return &f_synchronizer; } /* -------------------------------------------------------------------------- */ void FilteredSynchronizer::setupSynchronizer( const ElementSynchronizer & d_synchronizer, SynchElementFilter & filter) { AKANTU_DEBUG_IN(); std::vector<CommunicationRequest> isend_requests; std::map<UInt, Array<UInt> > keep_element_recv; auto rs_it = d_synchronizer.communications.begin_recv_scheme(); auto rs_end = d_synchronizer.communications.end_recv_scheme(); // Filter the recv list and communicate it to the sender processor for (; rs_it != rs_end; ++rs_it) { const auto & scheme = rs_it->second; auto & proc = rs_it->first; Array<UInt> & keep_element = keep_element_recv[proc]; auto & new_scheme = this->communications.createRecvScheme(proc); UInt el_pos = 0; for (const auto & element : scheme) { if (filter(element)) { new_scheme.push_back(element); keep_element.push_back(el_pos); } ++el_pos; } keep_element.push_back(-1); // just to be sure to send // something due to some shitty // MPI implementation who do not // know what to do with a 0 size // send Tag tag = Tag::genTag(this->rank, 0, RECEIVE_LIST_TAG); AKANTU_DEBUG_INFO("I have " << keep_element.getSize() - 1 << " elements to still receive from processor " << proc << " (communication tag : " << tag << ")"); isend_requests.push_back(communicator.asyncSend(keep_element, proc, tag)); } auto ss_it = d_synchronizer.communications.begin_send_scheme(); auto ss_end = d_synchronizer.communications.end_send_scheme(); // Receive the element to remove from the sender scheme for (; ss_it != ss_end; ++ss_it) { const auto & scheme = rs_it->second; auto & proc = rs_it->first; auto & new_scheme = this->communications.createSendScheme(proc); Tag tag = Tag::genTag(proc, 0, RECEIVE_LIST_TAG); AKANTU_DEBUG_INFO("Waiting list of elements to keep from processor " << proc << " (communication tag : " << tag << ")"); CommunicationStatus status; communicator.probe<UInt>(proc, tag, status); Array<UInt> keep_element(status.getSize()); AKANTU_DEBUG_INFO("I have " << keep_element.getSize() - 1 << " elements to keep in my send list to processor " << proc << " (communication tag : " << tag << ")"); communicator.receive(keep_element, proc, tag); for (UInt i = 0; i < keep_element.getSize() - 1; ++i) { new_scheme.push_back(scheme(keep_element(i))); } } communicator.waitAll(isend_requests); communicator.freeCommunicationRequest(isend_requests); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FilteredSynchronizer::updateElementList( Array<Element> * source_elements, Array<Element> * destination_elements, SynchElementFilter & filter) { AKANTU_DEBUG_IN(); // loop over procs for (UInt p = 0; p < this->nb_proc; ++p) { if (p == this->rank) continue; // access the element for this proc const Array<Element> & unfiltered_elements = source_elements[p]; Array<Element> & filtered_elements = destination_elements[p]; // iterator to loop over all source elements Array<Element>::const_iterator<Element> it = unfiltered_elements.begin(); Array<Element>::const_iterator<Element> end = unfiltered_elements.end(); // if filter accepts this element, push it into the destination elements for (; it != end; ++it) { const Element & element = *it; if (filter(element)) { filtered_elements.push_back(element); } } } AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu diff --git a/src/synchronizer/filtered_synchronizer.hh b/src/synchronizer/filtered_synchronizer.hh index 061b72ea9..6bd38e2ac 100644 --- a/src/synchronizer/filtered_synchronizer.hh +++ b/src/synchronizer/filtered_synchronizer.hh @@ -1,101 +1,101 @@ /** * @file filtered_synchronizer.hh * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Mathilde Radiguet <mathilde.radiguet@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Dec 08 2015 * * @brief synchronizer that filters elements from another synchronizer * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_FILTERED_SYNCHRONIZER_HH__ #define __AKANTU_FILTERED_SYNCHRONIZER_HH__ /* -------------------------------------------------------------------------- */ #include "element_synchronizer.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ class SynchElementFilter { public: virtual bool operator()(const Element &) = 0; }; /* -------------------------------------------------------------------------- */ class FilteredSynchronizer : public ElementSynchronizer { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FilteredSynchronizer(Mesh & mesh, SynchronizerID id = "filtered_synchronizer", MemoryID memory_id = 0); virtual ~FilteredSynchronizer() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// get another synchronizer and filter its elements using a functor static FilteredSynchronizer * createFilteredSynchronizer(const ElementSynchronizer & d_synchronizer, SynchElementFilter & filter); protected: /// set up the synchronizer void setupSynchronizer(const ElementSynchronizer & d_synchronizer, SynchElementFilter & filter); /// push source elements into destination elements through the filter void updateElementList(Array<Element> * source_elements, Array<Element> * destination_elements, SynchElementFilter & filter); protected: /// Define the receive list tag enum CommTags { RECEIVE_LIST_TAG = 0 }; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_FILTERED_SYNCHRONIZER_HH__ */ diff --git a/src/synchronizer/grid_synchronizer.cc b/src/synchronizer/grid_synchronizer.cc index 9ed515e30..7f92ca617 100644 --- a/src/synchronizer/grid_synchronizer.cc +++ b/src/synchronizer/grid_synchronizer.cc @@ -1,603 +1,603 @@ /** * @file grid_synchronizer.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Oct 03 2011 * @date last modification: Fri Jan 22 2016 * * @brief implementation of the grid synchronizer * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "grid_synchronizer.hh" #include "aka_grid_dynamic.hh" #include "mesh.hh" #include "fe_engine.hh" #include "integration_point.hh" #include "static_communicator.hh" #include "mesh_io.hh" #include <iostream> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ GridSynchronizer::GridSynchronizer(Mesh & mesh, const ID & id, MemoryID memory_id, const bool register_to_event_manager) : ElementSynchronizer(mesh, id, memory_id, register_to_event_manager) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class E> GridSynchronizer * GridSynchronizer::createGridSynchronizer( Mesh & mesh, const SpatialGrid<E> & grid, SynchronizerID id, SynchronizerRegistry * synchronizer_registry, const std::set<SynchronizationTag> & tags_to_register, MemoryID memory_id, const bool register_to_event_manager) { AKANTU_DEBUG_IN(); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); UInt nb_proc = comm.getNbProc(); UInt my_rank = comm.whoAmI(); GridSynchronizer & communicator = *(new GridSynchronizer(mesh, id, memory_id, register_to_event_manager)); if (nb_proc == 1) return &communicator; UInt spatial_dimension = mesh.getSpatialDimension(); Vector<Real> bounding_boxes(2 * spatial_dimension * nb_proc); Vector<Real> my_bounding_box(bounding_boxes.storage() + 2 * spatial_dimension * my_rank, 2 * spatial_dimension); // mesh.getLocalLowerBounds(my_bounding_box); // mesh.getLocalUpperBounds(my_bounding_box + spatial_dimension); const Vector<Real> & lower = grid.getLowerBounds(); const Vector<Real> & upper = grid.getUpperBounds(); const Vector<Real> & spacing = grid.getSpacing(); for (UInt i = 0; i < spatial_dimension; ++i) { my_bounding_box[i] = lower(i) - spacing(i); my_bounding_box[spatial_dimension + i] = upper(i) + spacing(i); } AKANTU_DEBUG_INFO( "Exchange of bounding box to detect the overlapping regions."); comm.allGather(bounding_boxes); bool * intersects_proc = new bool[nb_proc]; std::fill_n(intersects_proc, nb_proc, true); Int * first_cells = new Int[3 * nb_proc]; Int * last_cells = new Int[3 * nb_proc]; std::fill_n(first_cells, 3 * nb_proc, 0); std::fill_n(first_cells, 3 * nb_proc, 0); ElementTypeMapArray<UInt> ** element_per_proc = new ElementTypeMapArray<UInt> * [nb_proc]; for (UInt p = 0; p < nb_proc; ++p) element_per_proc[p] = NULL; // check the overlapping between my box and the one from other processors for (UInt p = 0; p < nb_proc; ++p) { if (p == my_rank) continue; Real * proc_bounding_box = bounding_boxes.storage() + 2 * spatial_dimension * p; bool intersects = false; Int * first_cell_p = first_cells + p * spatial_dimension; Int * last_cell_p = last_cells + p * spatial_dimension; for (UInt s = 0; s < spatial_dimension; ++s) { // check overlapping of grid intersects = Math::intersects( my_bounding_box[s], my_bounding_box[spatial_dimension + s], proc_bounding_box[s], proc_bounding_box[spatial_dimension + s]); intersects_proc[p] &= intersects; if (intersects) { AKANTU_DEBUG_INFO("I intersects with processor " << p << " in direction " << s); // is point 1 of proc p in the dimension s in the range ? bool point1 = Math::is_in_range(proc_bounding_box[s], my_bounding_box[s], my_bounding_box[s + spatial_dimension]); // is point 2 of proc p in the dimension s in the range ? bool point2 = Math::is_in_range( proc_bounding_box[s + spatial_dimension], my_bounding_box[s], my_bounding_box[s + spatial_dimension]); Real start = 0.; Real end = 0.; if (point1 && !point2) { /* |-----------| my_bounding_box(i) * |-----------| proc_bounding_box(i) * 1 2 */ start = proc_bounding_box[s]; end = my_bounding_box[s + spatial_dimension]; AKANTU_DEBUG_INFO("Intersection scheme 1 in direction " << s << " with processor " << p << " [" << start << ", " << end << "]"); } else if (point1 && point2) { /* |-----------------| my_bounding_box(i) * |-----------| proc_bounding_box(i) * 1 2 */ start = proc_bounding_box[s]; end = proc_bounding_box[s + spatial_dimension]; AKANTU_DEBUG_INFO("Intersection scheme 2 in direction " << s << " with processor " << p << " [" << start << ", " << end << "]"); } else if (!point1 && point2) { /* |-----------| my_bounding_box(i) * |-----------| proc_bounding_box(i) * 1 2 */ start = my_bounding_box[s]; end = proc_bounding_box[s + spatial_dimension]; AKANTU_DEBUG_INFO("Intersection scheme 3 in direction " << s << " with processor " << p << " [" << start << ", " << end << "]"); } else { /* |-----------| my_bounding_box(i) * |-----------------| proc_bounding_box(i) * 1 2 */ start = my_bounding_box[s]; end = my_bounding_box[s + spatial_dimension]; AKANTU_DEBUG_INFO("Intersection scheme 4 in direction " << s << " with processor " << p << " [" << start << ", " << end << "]"); } first_cell_p[s] = grid.getCellID(start, s); last_cell_p[s] = grid.getCellID(end, s); } } // create the list of cells in the overlapping typedef typename SpatialGrid<E>::CellID CellID; std::vector<CellID> * cell_ids = new std::vector<CellID>; if (intersects_proc[p]) { AKANTU_DEBUG_INFO("I intersects with processor " << p); CellID cell_id(spatial_dimension); // for (UInt i = 0; i < spatial_dimension; ++i) { // if(first_cell_p[i] != 0) --first_cell_p[i]; // if(last_cell_p[i] != 0) ++last_cell_p[i]; // } for (Int fd = first_cell_p[0]; fd <= last_cell_p[0]; ++fd) { cell_id.setID(0, fd); if (spatial_dimension == 1) { cell_ids->push_back(cell_id); } else { for (Int sd = first_cell_p[1]; sd <= last_cell_p[1]; ++sd) { cell_id.setID(1, sd); if (spatial_dimension == 2) { cell_ids->push_back(cell_id); } else { for (Int ld = first_cell_p[2]; ld <= last_cell_p[2]; ++ld) { cell_id.setID(2, ld); cell_ids->push_back(cell_id); } } } } } // get the list of elements in the cells of the overlapping typename std::vector<CellID>::iterator cur_cell_id = cell_ids->begin(); typename std::vector<CellID>::iterator last_cell_id = cell_ids->end(); std::set<Element> * to_send = new std::set<Element>(); for (; cur_cell_id != last_cell_id; ++cur_cell_id) { typename SpatialGrid<E>::Cell::const_iterator cur_elem = grid.beginCell(*cur_cell_id); typename SpatialGrid<E>::Cell::const_iterator last_elem = grid.endCell(*cur_cell_id); for (; cur_elem != last_elem; ++cur_elem) { to_send->insert(*cur_elem); } } AKANTU_DEBUG_INFO("I have prepared " << to_send->size() << " elements to send to processor " << p); auto & scheme = communicator.getCommunications().createSendScheme(p); std::stringstream sstr; sstr << "element_per_proc_" << p; element_per_proc[p] = new ElementTypeMapArray<UInt>(sstr.str(), id, memory_id); ElementTypeMapArray<UInt> & elempproc = *(element_per_proc[p]); typename std::set<Element>::iterator elem = to_send->begin(); typename std::set<Element>::iterator last_elem = to_send->end(); for (; elem != last_elem; ++elem) { ElementType type = elem->type; UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); // /!\ this part must be slow due to the access in the // ElementTypeMapArray<UInt> if (!elempproc.exists(type, _not_ghost)) elempproc.alloc(0, nb_nodes_per_element, type, _not_ghost); Vector<UInt> global_connect(nb_nodes_per_element); UInt * local_connect = mesh.getConnectivity(type).storage() + elem->element * nb_nodes_per_element; for (UInt i = 0; i < nb_nodes_per_element; ++i) { global_connect(i) = mesh.getNodeGlobalId(local_connect[i]); AKANTU_DEBUG_ASSERT( global_connect(i) < mesh.getNbGlobalNodes(), "This global node send in the connectivity does not seem correct " << global_connect(i) << " corresponding to " << local_connect[i] << " from element " << elem->element); } elempproc(type).push_back(global_connect); scheme.push_back(*elem); } delete to_send; } delete cell_ids; } delete[] first_cells; delete[] last_cells; AKANTU_DEBUG_INFO("I have finished to compute intersection," << " no it's time to communicate with my neighbors"); /** * Sending loop, sends the connectivity asynchronously to all concerned proc */ std::vector<CommunicationRequest> isend_requests; UInt * space = new UInt[2*nb_proc*_max_element_type]; UInt offset = 0; for (UInt p = 0; p < nb_proc; ++p) { if (p == my_rank) continue; if (intersects_proc[p]) { ElementTypeMapArray<UInt> & elempproc = *(element_per_proc[p]); ElementTypeMapArray<UInt>::type_iterator it_type = elempproc.firstType(_all_dimensions, _not_ghost); ElementTypeMapArray<UInt>::type_iterator last_type = elempproc.lastType(_all_dimensions, _not_ghost); UInt count = 0; for (; it_type != last_type; ++it_type) { Array<UInt> & conn = elempproc(*it_type, _not_ghost); Vector<UInt> info(space + offset, 2); offset += 2; info[0] = (UInt)*it_type; info[1] = conn.getSize() * conn.getNbComponent(); AKANTU_DEBUG_INFO("I have " << conn.getSize() << " elements of type " << *it_type << " to send to processor " << p << " (communication tag : " << Tag::genTag(my_rank, count, DATA_TAG) << ")"); isend_requests.push_back( comm.asyncSend(info, p, Tag::genTag(my_rank, count, SIZE_TAG))); if (info[1] != 0) isend_requests.push_back( comm.asyncSend<UInt>(conn, p, Tag::genTag(my_rank, count, DATA_TAG))); ++count; } Vector<UInt> info(space + offset, 2); offset += 2; info[0] = (UInt)_not_defined; info[1] = 0; isend_requests.push_back( comm.asyncSend(info, p, Tag::genTag(my_rank, count, SIZE_TAG))); } } /** * Receives the connectivity and store them in the ghosts elements */ Array<UInt> & global_nodes_ids = const_cast<Array<UInt> &>(mesh.getGlobalNodesIds()); Array<NodeType> & nodes_type = const_cast<Array<NodeType> &>(const_cast<const Mesh &>(mesh).getNodesType()); std::vector<CommunicationRequest> isend_nodes_requests; Vector<UInt> nb_nodes_to_recv(nb_proc); UInt nb_total_nodes_to_recv = 0; UInt nb_current_nodes = global_nodes_ids.getSize(); NewNodesEvent new_nodes; NewElementsEvent new_elements; Array<UInt> * ask_nodes_per_proc = new Array<UInt>[nb_proc]; for (UInt p = 0; p < nb_proc; ++p) { nb_nodes_to_recv(p) = 0; if (p == my_rank) continue; auto & scheme = communicator.getCommunications().createRecvScheme(p); Array<UInt> & ask_nodes = ask_nodes_per_proc[p]; UInt count = 0; if (intersects_proc[p]) { ElementType type = _not_defined; do { Vector<UInt> info(2); comm.receive(info, p, Tag::genTag(p, count, SIZE_TAG)); type = (ElementType)info[0]; if (type != _not_defined) { UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); ; UInt nb_element = info[1] / nb_nodes_per_element; Array<UInt> tmp_conn(nb_element, nb_nodes_per_element); tmp_conn.clear(); if (info[1] != 0) comm.receive<UInt>(tmp_conn, p, Tag::genTag(p, count, DATA_TAG)); AKANTU_DEBUG_INFO("I will receive " << nb_element << " elements of type " << ElementType(info[0]) << " from processor " << p << " (communication tag : " << Tag::genTag(p, count, DATA_TAG) << ")"); Array<UInt> & ghost_connectivity = const_cast<Array<UInt> &>(mesh.getConnectivity(type, _ghost)); UInt nb_ghost_element = ghost_connectivity.getSize(); Element element(type, 0, _ghost); Vector<UInt> conn(nb_nodes_per_element); for (UInt el = 0; el < nb_element; ++el) { UInt nb_node_to_ask_for_elem = 0; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt gn = tmp_conn(el, n); UInt ln = global_nodes_ids.find(gn); AKANTU_DEBUG_ASSERT(gn < mesh.getNbGlobalNodes(), "This global node seems not correct " << gn << " from element " << el << " node " << n); if (ln == UInt(-1)) { global_nodes_ids.push_back(gn); nodes_type.push_back(_nt_pure_gost); // pure ghost node ln = nb_current_nodes; new_nodes.getList().push_back(ln); ++nb_current_nodes; ask_nodes.push_back(gn); ++nb_node_to_ask_for_elem; } conn[n] = ln; } // all the nodes are already known locally, the element should // already exists UInt c = UInt(-1); if (nb_node_to_ask_for_elem == 0) { c = ghost_connectivity.find(conn); element.element = c; } if (c == UInt(-1)) { element.element = nb_ghost_element; ++nb_ghost_element; ghost_connectivity.push_back(conn); new_elements.getList().push_back(element); } scheme.push_back(element); } } count++; } while (type != _not_defined); AKANTU_DEBUG_INFO("I have " << ask_nodes.getSize() << " missing nodes for elements coming from processor " << p << " (communication tag : " << Tag::genTag(my_rank, 0, ASK_NODES_TAG) << ")"); ask_nodes.push_back(UInt(-1)); isend_nodes_requests.push_back( comm.asyncSend(ask_nodes, p, Tag::genTag(my_rank, 0, ASK_NODES_TAG))); nb_nodes_to_recv(p) = ask_nodes.getSize() - 1; nb_total_nodes_to_recv += nb_nodes_to_recv(p); } } comm.waitAll(isend_requests); comm.freeCommunicationRequest(isend_requests); delete [] space; for (UInt p = 0; p < nb_proc; ++p) { if (element_per_proc[p]) delete element_per_proc[p]; } delete[] element_per_proc; /** * Sends requested nodes to proc */ Array<Real> & nodes = const_cast<Array<Real> &>(mesh.getNodes()); UInt nb_nodes = nodes.getSize(); std::vector<CommunicationRequest> isend_coordinates_requests; Array<Real> * nodes_to_send_per_proc = new Array<Real>[nb_proc]; for (UInt p = 0; p < nb_proc; ++p) { if (p == my_rank || !intersects_proc[p]) continue; Array<UInt> asked_nodes; CommunicationStatus status; AKANTU_DEBUG_INFO("Waiting list of nodes to send to processor " << p << "(communication tag : " << Tag::genTag(p, 0, ASK_NODES_TAG) << ")"); comm.probe<UInt>(p, Tag::genTag(p, 0, ASK_NODES_TAG), status); UInt nb_nodes_to_send = status.getSize(); asked_nodes.resize(nb_nodes_to_send); AKANTU_DEBUG_INFO("I have " << nb_nodes_to_send - 1 << " nodes to send to processor " << p << " (communication tag : " << Tag::genTag(p, 0, ASK_NODES_TAG) << ")"); AKANTU_DEBUG_INFO("Getting list of nodes to send to processor " << p << " (communication tag : " << Tag::genTag(p, 0, ASK_NODES_TAG) << ")"); comm.receive(asked_nodes, p, Tag::genTag(p, 0, ASK_NODES_TAG)); nb_nodes_to_send--; asked_nodes.resize(nb_nodes_to_send); Array<Real> & nodes_to_send = nodes_to_send_per_proc[p]; nodes_to_send.extendComponentsInterlaced(spatial_dimension, 1); auto it = nodes.begin(spatial_dimension); for (UInt n = 0; n < nb_nodes_to_send; ++n) { UInt ln = global_nodes_ids.find(asked_nodes(n)); AKANTU_DEBUG_ASSERT(ln != UInt(-1), "The node [" << asked_nodes(n) << "] requested by proc " << p << " was not found locally!"); nodes_to_send.push_back(it + ln); } if (nb_nodes_to_send != 0) { AKANTU_DEBUG_INFO("Sending the " << nb_nodes_to_send << " nodes to processor " << p << " (communication tag : " << Tag::genTag(p, 0, SEND_NODES_TAG) << ")"); isend_coordinates_requests.push_back(comm.asyncSend( nodes_to_send, p, Tag::genTag(my_rank, 0, SEND_NODES_TAG))); } #if not defined(AKANTU_NDEBUG) else { AKANTU_DEBUG_INFO("No nodes to send to processor " << p); } #endif } comm.waitAll(isend_nodes_requests); comm.freeCommunicationRequest(isend_nodes_requests); delete[] ask_nodes_per_proc; nodes.resize(nb_total_nodes_to_recv + nb_nodes); for (UInt p = 0; p < nb_proc; ++p) { if ((p != my_rank) && (nb_nodes_to_recv(p) > 0)) { AKANTU_DEBUG_INFO("Receiving the " << nb_nodes_to_recv(p) << " nodes from processor " << p << " (communication tag : " << Tag::genTag(p, 0, SEND_NODES_TAG) << ")"); Vector<Real> nodes_to_recv(nodes.storage() + nb_nodes * spatial_dimension, nb_nodes_to_recv(p) * spatial_dimension); comm.receive(nodes_to_recv, p, Tag::genTag(p, 0, SEND_NODES_TAG)); nb_nodes += nb_nodes_to_recv(p); } #if not defined(AKANTU_NDEBUG) else { if (p != my_rank) { AKANTU_DEBUG_INFO("No nodes to receive from processor " << p); } } #endif } comm.waitAll(isend_coordinates_requests); comm.freeCommunicationRequest(isend_coordinates_requests); delete[] nodes_to_send_per_proc; // Register the tags if any if (synchronizer_registry) { std::set<SynchronizationTag>::const_iterator it = tags_to_register.begin(); std::set<SynchronizationTag>::const_iterator end = tags_to_register.end(); for (; it != end; ++it) { synchronizer_registry->registerSynchronizer(communicator, *it); } } mesh.sendEvent(new_nodes); mesh.sendEvent(new_elements); delete[] intersects_proc; AKANTU_DEBUG_OUT(); return &communicator; } /* -------------------------------------------------------------------------- */ template GridSynchronizer * GridSynchronizer::createGridSynchronizer<IntegrationPoint>( Mesh & mesh, const SpatialGrid<IntegrationPoint> & grid, SynchronizerID id, SynchronizerRegistry * synchronizer_registry, const std::set<SynchronizationTag> & tags_to_register, MemoryID memory_id, const bool register_to_event_manager); template GridSynchronizer * GridSynchronizer::createGridSynchronizer<Element>( Mesh & mesh, const SpatialGrid<Element> & grid, SynchronizerID id, SynchronizerRegistry * synchronizer_registry, const std::set<SynchronizationTag> & tags_to_register, MemoryID memory_id, const bool register_to_event_manager); -__END_AKANTU__ +} // akantu diff --git a/src/synchronizer/grid_synchronizer.hh b/src/synchronizer/grid_synchronizer.hh index cc0677855..431feaf04 100644 --- a/src/synchronizer/grid_synchronizer.hh +++ b/src/synchronizer/grid_synchronizer.hh @@ -1,99 +1,99 @@ /** * @file grid_synchronizer.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Dec 08 2015 * * @brief Synchronizer based on spatial grid * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "element_synchronizer.hh" #include "synchronizer_registry.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_GRID_SYNCHRONIZER_HH__ #define __AKANTU_GRID_SYNCHRONIZER_HH__ -__BEGIN_AKANTU__ +namespace akantu { class Mesh; template <class T> class SpatialGrid; class GridSynchronizer : public ElementSynchronizer { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ protected: GridSynchronizer(Mesh & mesh, const ID & id = "grid_synchronizer", MemoryID memory_id = 0, const bool register_to_event_manager = true); public: virtual ~GridSynchronizer(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /** *Create the Grid Synchronizer: *Compute intersection and send info to neighbours that will be stored in *ghosts elements */ template <class E> static GridSynchronizer * createGridSynchronizer(Mesh & mesh, const SpatialGrid<E> & grid, SynchronizerID id = "grid_synchronizer", SynchronizerRegistry * synch_registry = NULL, const std::set<SynchronizationTag> & tags_to_register = std::set<SynchronizationTag>(), MemoryID memory_id = 0, const bool register_to_event_manager = true); protected: /// Define the tags that will be used in the send and receive instructions enum CommTags { SIZE_TAG = 0, DATA_TAG = 1, ASK_NODES_TAG = 2, SEND_NODES_TAG = 3 }; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_GRID_SYNCHRONIZER_HH__ */ diff --git a/src/synchronizer/master_element_info_per_processor.cc b/src/synchronizer/master_element_info_per_processor.cc index cc685c156..44560563c 100644 --- a/src/synchronizer/master_element_info_per_processor.cc +++ b/src/synchronizer/master_element_info_per_processor.cc @@ -1,490 +1,490 @@ /** * @file master_element_info_per_processor.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Fri Mar 11 14:57:13 2016 * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "element_group.hh" #include "element_info_per_processor.hh" #include "element_synchronizer.hh" #include "mesh_utils.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ #include <algorithm> #include <iostream> #include <map> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ MasterElementInfoPerProc::MasterElementInfoPerProc( ElementSynchronizer & synchronizer, UInt message_cnt, UInt root, ElementType type, const MeshPartition & partition) : ElementInfoPerProc(synchronizer, message_cnt, root, type), partition(partition), all_nb_local_element(nb_proc, 0), all_nb_ghost_element(nb_proc, 0), all_nb_element_to_send(nb_proc, 0) { Vector<UInt> size(5); size(0) = (UInt)type; if (type != _not_defined) { nb_nodes_per_element = Mesh::getNbNodesPerElement(type); nb_element = mesh.getNbElement(type); const Array<UInt> & partition_num = this->partition.getPartition(this->type, _not_ghost); const CSR<UInt> & ghost_partition = this->partition.getGhostPartitionCSR()(this->type, _not_ghost); for (UInt el = 0; el < nb_element; ++el) { this->all_nb_local_element[partition_num(el)]++; for (CSR<UInt>::const_iterator part = ghost_partition.begin(el); part != ghost_partition.end(el); ++part) { this->all_nb_ghost_element[*part]++; } this->all_nb_element_to_send[partition_num(el)] += ghost_partition.getNbCols(el) + 1; } /// tag info std::vector<std::string> tag_names; this->getMeshData().getTagNames(tag_names, type); this->nb_tags = tag_names.size(); size(4) = nb_tags; for (UInt p = 0; p < nb_proc; ++p) { if (p != root) { size(1) = this->all_nb_local_element[p]; size(2) = this->all_nb_ghost_element[p]; size(3) = this->all_nb_element_to_send[p]; AKANTU_DEBUG_INFO( "Sending connectivities informations to proc " << p << " TAG(" << Tag::genTag(this->rank, this->message_count, Tag::_SIZES) << ")"); comm.send(size, p, Tag::genTag(this->rank, this->message_count, Tag::_SIZES)); } else { this->nb_local_element = this->all_nb_local_element[p]; this->nb_ghost_element = this->all_nb_ghost_element[p]; } } } else { for (UInt p = 0; p < this->nb_proc; ++p) { if (p != this->root) { AKANTU_DEBUG_INFO( "Sending empty connectivities informations to proc " << p << " TAG(" << Tag::genTag(this->rank, this->message_count, Tag::_SIZES) << ")"); comm.send(size, p, Tag::genTag(this->rank, this->message_count, Tag::_SIZES)); } } } } /* ------------------------------------------------------------------------ */ void MasterElementInfoPerProc::synchronizeConnectivities() { const Array<UInt> & partition_num = this->partition.getPartition(this->type, _not_ghost); const CSR<UInt> & ghost_partition = this->partition.getGhostPartitionCSR()(this->type, _not_ghost); std::vector<Array<UInt>> buffers(this->nb_proc); auto conn_it = this->mesh.getConnectivity(this->type, _not_ghost) .begin(this->nb_nodes_per_element); auto conn_end = this->mesh.getConnectivity(this->type, _not_ghost) .end(this->nb_nodes_per_element); /// copying the local connectivity auto part_it = partition_num.begin(); for (; conn_it != conn_end; ++conn_it, ++part_it) { const auto & conn = *conn_it; for (UInt i = 0; i < conn.size(); ++i) { buffers[*part_it].push_back(conn[i]); } } /// copying the connectivity of ghost element conn_it = this->mesh.getConnectivity(this->type, _not_ghost) .begin(this->nb_nodes_per_element); for (UInt el = 0; conn_it != conn_end; ++el, ++conn_it) { for (auto part = ghost_partition.begin(el); part != ghost_partition.end(el); ++part) { UInt proc = *part; const Vector<UInt> & conn = *conn_it; for (UInt i = 0; i < conn.size(); ++i) { buffers[proc].push_back(conn[i]); } } } #ifndef AKANTU_NDEBUG for (UInt p = 0; p < this->nb_proc; ++p) { UInt size = this->nb_nodes_per_element * (this->all_nb_local_element[p] + this->all_nb_ghost_element[p]); AKANTU_DEBUG_ASSERT( buffers[p].getSize() == size, "The connectivity data packed in the buffer are not correct"); } #endif /// send all connectivity and ghost information to all processors std::vector<CommunicationRequest> requests; for (UInt p = 0; p < this->nb_proc; ++p) { if (p != this->root) { AKANTU_DEBUG_INFO( "Sending connectivities to proc " << p << " TAG(" << Tag::genTag(this->rank, this->message_count, Tag::_CONNECTIVITY) << ")"); requests.push_back(comm.asyncSend( buffers[p], p, Tag::genTag(this->rank, this->message_count, Tag::_CONNECTIVITY))); } } Array<UInt> & old_nodes = this->getNodesGlobalIds(); /// create the renumbered connectivity AKANTU_DEBUG_INFO("Renumbering local connectivities"); MeshUtils::renumberMeshNodes(mesh, buffers[root], all_nb_local_element[root], all_nb_ghost_element[root], type, old_nodes); comm.waitAll(requests); comm.freeCommunicationRequest(requests); } /* ------------------------------------------------------------------------ */ void MasterElementInfoPerProc::synchronizePartitions() { const Array<UInt> & partition_num = this->partition.getPartition(this->type, _not_ghost); const CSR<UInt> & ghost_partition = this->partition.getGhostPartitionCSR()(this->type, _not_ghost); std::vector<Array<UInt>> buffers(this->partition.getNbPartition()); /// splitting the partition information to send them to processors Vector<UInt> count_by_proc(nb_proc, 0); for (UInt el = 0; el < nb_element; ++el) { UInt proc = partition_num(el); buffers[proc].push_back(ghost_partition.getNbCols(el)); UInt i(0); for (CSR<UInt>::const_iterator part = ghost_partition.begin(el); part != ghost_partition.end(el); ++part, ++i) { buffers[proc].push_back(*part); } } for (UInt el = 0; el < nb_element; ++el) { UInt i(0); for (CSR<UInt>::const_iterator part = ghost_partition.begin(el); part != ghost_partition.end(el); ++part, ++i) { buffers[*part].push_back(partition_num(el)); } } #ifndef AKANTU_NDEBUG for (UInt p = 0; p < this->nb_proc; ++p) { AKANTU_DEBUG_ASSERT( buffers[p].getSize() == (this->all_nb_ghost_element[p] + this->all_nb_element_to_send[p]), "Data stored in the buffer are most probably wrong"); } #endif std::vector<CommunicationRequest> requests; /// last data to compute the communication scheme for (UInt p = 0; p < this->nb_proc; ++p) { if (p != this->root) { AKANTU_DEBUG_INFO( "Sending partition informations to proc " << p << " TAG(" << Tag::genTag(this->rank, this->message_count, Tag::_PARTITIONS) << ")"); requests.push_back(comm.asyncSend( buffers[p], p, Tag::genTag(this->rank, this->message_count, Tag::_PARTITIONS))); } } if (Mesh::getSpatialDimension(this->type) == this->mesh.getSpatialDimension()) { AKANTU_DEBUG_INFO("Creating communications scheme"); this->fillCommunicationScheme(buffers[this->rank]); } comm.waitAll(requests); comm.freeCommunicationRequest(requests); } /* -------------------------------------------------------------------------- */ void MasterElementInfoPerProc::synchronizeTags() { AKANTU_DEBUG_IN(); if (this->nb_tags == 0) { AKANTU_DEBUG_OUT(); return; } UInt mesh_data_sizes_buffer_length; MeshData & mesh_data = this->getMeshData(); /// tag info std::vector<std::string> tag_names; mesh_data.getTagNames(tag_names, type); // Make sure the tags are sorted (or at least not in random order), // because they come from a map !! std::sort(tag_names.begin(), tag_names.end()); // Sending information about the tags in mesh_data: name, data type and // number of components of the underlying array associated to the current // type DynamicCommunicationBuffer mesh_data_sizes_buffer; std::vector<std::string>::const_iterator names_it = tag_names.begin(); std::vector<std::string>::const_iterator names_end = tag_names.end(); for (; names_it != names_end; ++names_it) { mesh_data_sizes_buffer << *names_it; mesh_data_sizes_buffer << mesh_data.getTypeCode(*names_it); mesh_data_sizes_buffer << mesh_data.getNbComponent(*names_it, type); } mesh_data_sizes_buffer_length = mesh_data_sizes_buffer.getSize(); AKANTU_DEBUG_INFO( "Broadcasting the size of the information about the mesh data tags: (" << mesh_data_sizes_buffer_length << ")."); comm.broadcast(mesh_data_sizes_buffer_length, root); AKANTU_DEBUG_INFO( "Broadcasting the information about the mesh data tags, addr " << (void *)mesh_data_sizes_buffer.storage()); if (mesh_data_sizes_buffer_length != 0) comm.broadcast(mesh_data_sizes_buffer, root); if (mesh_data_sizes_buffer_length != 0) { // Sending the actual data to each processor DynamicCommunicationBuffer * buffers = new DynamicCommunicationBuffer[nb_proc]; std::vector<std::string>::const_iterator names_it = tag_names.begin(); std::vector<std::string>::const_iterator names_end = tag_names.end(); // Loop over each tag for the current type for (; names_it != names_end; ++names_it) { // Type code of the current tag (i.e. the tag named *names_it) this->fillTagBuffer(buffers, *names_it); } std::vector<CommunicationRequest> requests; for (UInt p = 0; p < nb_proc; ++p) { if (p != root) { AKANTU_DEBUG_INFO("Sending " << buffers[p].getSize() << " bytes of mesh data to proc " << p << " TAG(" << Tag::genTag(this->rank, this->message_count, Tag::_MESH_DATA) << ")"); requests.push_back(comm.asyncSend( buffers[p], p, Tag::genTag(this->rank, this->message_count, Tag::_MESH_DATA))); } } names_it = tag_names.begin(); // Loop over each tag for the current type for (; names_it != names_end; ++names_it) { // Reinitializing the mesh data on the master this->fillMeshData(buffers[root], *names_it, mesh_data.getTypeCode(*names_it), mesh_data.getNbComponent(*names_it, type)); } comm.waitAll(requests); comm.freeCommunicationRequest(requests); requests.clear(); delete[] buffers; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <typename T> void MasterElementInfoPerProc::fillTagBufferTemplated( DynamicCommunicationBuffer * buffers, const std::string & tag_name) { MeshData & mesh_data = this->getMeshData(); const Array<T> & data = mesh_data.getElementalDataArray<T>(tag_name, type); const Array<UInt> & partition_num = this->partition.getPartition(this->type, _not_ghost); const CSR<UInt> & ghost_partition = this->partition.getGhostPartitionCSR()(this->type, _not_ghost); // Not possible to use the iterator because it potentially triggers the // creation of complex // type templates (such as akantu::Vector< std::vector<Element> > which don't // implement the right interface // (e.g. operator<< in that case). // typename Array<T>::template const_iterator< Vector<T> > data_it = // data.begin(data.getNbComponent()); // typename Array<T>::template const_iterator< Vector<T> > data_end = // data.end(data.getNbComponent()); const T * data_it = data.storage(); const T * data_end = data.storage() + data.getSize() * data.getNbComponent(); const UInt * part = partition_num.storage(); /// copying the data, element by element for (; data_it != data_end; ++part) { for (UInt j(0); j < data.getNbComponent(); ++j, ++data_it) { buffers[*part] << *data_it; } } data_it = data.storage(); /// copying the data for the ghost element for (UInt el(0); data_it != data_end; data_it += data.getNbComponent(), ++el) { CSR<UInt>::const_iterator it = ghost_partition.begin(el); CSR<UInt>::const_iterator end = ghost_partition.end(el); for (; it != end; ++it) { UInt proc = *it; for (UInt j(0); j < data.getNbComponent(); ++j) { buffers[proc] << data_it[j]; } } } } /* -------------------------------------------------------------------------- */ void MasterElementInfoPerProc::fillTagBuffer( DynamicCommunicationBuffer * buffers, const std::string & tag_name) { MeshData & mesh_data = this->getMeshData(); #define AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA(r, extra_param, elem) \ case BOOST_PP_TUPLE_ELEM(2, 0, elem): { \ this->fillTagBufferTemplated<BOOST_PP_TUPLE_ELEM(2, 1, elem)>(buffers, \ tag_name); \ break; \ } MeshDataTypeCode data_type_code = mesh_data.getTypeCode(tag_name); switch (data_type_code) { BOOST_PP_SEQ_FOR_EACH(AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA, , AKANTU_MESH_DATA_TYPES) default: AKANTU_DEBUG_ERROR("Could not obtain the type of tag" << tag_name << "!"); break; } #undef AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA } /* -------------------------------------------------------------------------- */ void MasterElementInfoPerProc::synchronizeGroups() { AKANTU_DEBUG_IN(); DynamicCommunicationBuffer * buffers = new DynamicCommunicationBuffer[nb_proc]; typedef std::vector<std::vector<std::string>> ElementToGroup; ElementToGroup element_to_group; element_to_group.resize(nb_element); GroupManager::const_element_group_iterator egi = mesh.element_group_begin(); GroupManager::const_element_group_iterator ege = mesh.element_group_end(); for (; egi != ege; ++egi) { ElementGroup & eg = *(egi->second); std::string name = egi->first; ElementGroup::const_element_iterator eit = eg.element_begin(type, _not_ghost); ElementGroup::const_element_iterator eend = eg.element_end(type, _not_ghost); for (; eit != eend; ++eit) { element_to_group[*eit].push_back(name); } eit = eg.element_begin(type, _not_ghost); if (eit != eend) const_cast<Array<UInt> &>(eg.getElements(type)).empty(); } const Array<UInt> & partition_num = this->partition.getPartition(this->type, _not_ghost); const CSR<UInt> & ghost_partition = this->partition.getGhostPartitionCSR()(this->type, _not_ghost); /// preparing the buffers const UInt * part = partition_num.storage(); /// copying the data, element by element ElementToGroup::const_iterator data_it = element_to_group.begin(); ElementToGroup::const_iterator data_end = element_to_group.end(); for (; data_it != data_end; ++part, ++data_it) { buffers[*part] << *data_it; } data_it = element_to_group.begin(); /// copying the data for the ghost element for (UInt el(0); data_it != data_end; ++data_it, ++el) { CSR<UInt>::const_iterator it = ghost_partition.begin(el); CSR<UInt>::const_iterator end = ghost_partition.end(el); for (; it != end; ++it) { UInt proc = *it; buffers[proc] << *data_it; } } std::vector<CommunicationRequest> requests; for (UInt p = 0; p < this->nb_proc; ++p) { if (p == this->rank) continue; AKANTU_DEBUG_INFO("Sending element groups to proc " << p << " TAG(" << Tag::genTag(this->rank, p, Tag::_ELEMENT_GROUP) << ")"); requests.push_back(comm.asyncSend( buffers[p], p, Tag::genTag(this->rank, p, Tag::_ELEMENT_GROUP))); } this->fillElementGroupsFromBuffer(buffers[this->rank]); comm.waitAll(requests); comm.freeCommunicationRequest(requests); requests.clear(); delete[] buffers; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/synchronizer/mpi_type_wrapper.hh b/src/synchronizer/mpi_type_wrapper.hh index cd58a6af9..4173d148e 100644 --- a/src/synchronizer/mpi_type_wrapper.hh +++ b/src/synchronizer/mpi_type_wrapper.hh @@ -1,109 +1,109 @@ /** * @file mpi_type_wrapper.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Jun 14 2010 * @date last modification: Wed Oct 07 2015 * * @brief Wrapper on MPI types to have a better separation between libraries * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #if defined(__INTEL_COMPILER) //#pragma warning ( disable : 383 ) #elif defined(__clang__) // test clang to be sure that when we test for gnu it // is only gnu #elif (defined(__GNUC__) || defined(__GNUG__)) #if __cplusplus > 199711L #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wliteral-suffix" #endif #endif #include <mpi.h> #if defined(__INTEL_COMPILER) //#pragma warning ( disable : 383 ) #elif defined(__clang__) // test clang to be sure that when we test for gnu it // is only gnu #elif (defined(__GNUC__) || defined(__GNUG__)) #if __cplusplus > 199711L #pragma GCC diagnostic pop #endif #endif /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "static_communicator_mpi.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MPI_TYPE_WRAPPER_HH__ #define __AKANTU_MPI_TYPE_WRAPPER_HH__ -__BEGIN_AKANTU__ +namespace akantu { class MPITypeWrapper { public: MPITypeWrapper(StaticCommunicatorMPI & static_comm) : static_comm(static_comm), communicator(MPI_COMM_WORLD), max_tag(0) {} template <typename T> static inline MPI_Datatype getMPIDatatype(); inline void setMPICommunicator(MPI_Comm comm) { communicator = comm; int prank, psize; MPI_Comm_rank(communicator, &prank); MPI_Comm_size(communicator, &psize); static_comm.setRank(prank); static_comm.setSize(psize); int flag; int * value; MPI_Comm_get_attr(comm, MPI_TAG_UB, &value, &flag); AKANTU_DEBUG_ASSERT(flag, "No attribute MPI_TAG_UB."); this->max_tag = *value; } inline MPI_Comm getMPICommunicator() const { return communicator; } static MPI_Op getMPISynchronizerOperation(const SynchronizerOperation & op) { return synchronizer_operation_to_mpi_op[op]; } inline int getMaxTag() const { return this->max_tag; } private: StaticCommunicatorMPI & static_comm; MPI_Comm communicator; int max_tag; static MPI_Op synchronizer_operation_to_mpi_op[_so_null + 1]; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_MPI_TYPE_WRAPPER_HH__ */ diff --git a/src/synchronizer/node_info_per_processor.cc b/src/synchronizer/node_info_per_processor.cc index 25365bda2..5f461736c 100644 --- a/src/synchronizer/node_info_per_processor.cc +++ b/src/synchronizer/node_info_per_processor.cc @@ -1,500 +1,500 @@ /** * @file node_info_per_processor.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Fri Mar 11 15:49:43 2016 * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "node_info_per_processor.hh" #include "node_group.hh" #include "node_synchronizer.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ #include <algorithm> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ NodeInfoPerProc::NodeInfoPerProc(NodeSynchronizer & synchronizer, UInt message_cnt, UInt root) : MeshAccessor(synchronizer.getMesh()), synchronizer(synchronizer), comm(synchronizer.getCommunicator()), rank(comm.whoAmI()), nb_proc(comm.getNbProc()), root(root), mesh(synchronizer.getMesh()), spatial_dimension(synchronizer.getMesh().getSpatialDimension()), message_count(message_cnt) {} /* -------------------------------------------------------------------------- */ template <class CommunicationBuffer> void NodeInfoPerProc::fillNodeGroupsFromBuffer(CommunicationBuffer & buffer) { AKANTU_DEBUG_IN(); std::vector<std::vector<std::string>> node_to_group; buffer >> node_to_group; AKANTU_DEBUG_ASSERT(node_to_group.size() == mesh.getNbGlobalNodes(), "Not the good amount of nodes where transmitted"); const auto & global_nodes = mesh.getGlobalNodesIds(); auto nbegin = global_nodes.begin(); auto nit = global_nodes.begin(); auto nend = global_nodes.end(); for (; nit != nend; ++nit) { std::vector<std::string>::iterator it = node_to_group[*nit].begin(); std::vector<std::string>::iterator end = node_to_group[*nit].end(); for (; it != end; ++it) { mesh.getNodeGroup(*it).add(nit - nbegin, false); } } GroupManager::const_node_group_iterator ngi = mesh.node_group_begin(); GroupManager::const_node_group_iterator nge = mesh.node_group_end(); for (; ngi != nge; ++ngi) { NodeGroup & ng = *(ngi->second); ng.optimize(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void NodeInfoPerProc::fillNodesType() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); Array<NodeType> & nodes_type = this->getNodesType(); Array<UInt> nodes_set(nb_nodes); nodes_set.set(0); enum NodeSet { NORMAL_SET = 1, GHOST_SET = 2, }; Array<bool> already_seen(nb_nodes, 1, false); for (UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType)g; UInt set = NORMAL_SET; if (gt == _ghost) set = GHOST_SET; already_seen.set(false); Mesh::type_iterator it = mesh.firstType(_all_dimensions, gt, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(_all_dimensions, gt, _ek_not_defined); for (; it != end; ++it) { ElementType type = *it; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_element = mesh.getNbElement(type, gt); Array<UInt>::const_vector_iterator conn_it = mesh.getConnectivity(type, gt).begin(nb_nodes_per_element); for (UInt e = 0; e < nb_element; ++e, ++conn_it) { const Vector<UInt> & conn = *conn_it; for (UInt n = 0; n < nb_nodes_per_element; ++n) { AKANTU_DEBUG_ASSERT(conn(n) < nb_nodes, "Node " << conn(n) << " bigger than number of nodes " << nb_nodes); if (!already_seen(conn(n))) { nodes_set(conn(n)) += set; already_seen(conn(n)) = true; } } } } } for (UInt i = 0; i < nb_nodes; ++i) { if (nodes_set(i) == NORMAL_SET) nodes_type(i) = _nt_normal; else if (nodes_set(i) == GHOST_SET) nodes_type(i) = _nt_pure_gost; else if (nodes_set(i) == (GHOST_SET + NORMAL_SET)) nodes_type(i) = _nt_master; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void NodeInfoPerProc::fillCommunicationScheme(const Array<UInt> & master_info) { AKANTU_DEBUG_IN(); Communications<UInt> & communications = this->synchronizer.getCommunications(); { // send schemes auto it = master_info.begin_reinterpret(2, master_info.getSize() / 2); auto end = master_info.end_reinterpret(2, master_info.getSize() / 2); std::map<UInt, Array<UInt>> send_array_per_proc; for (; it != end; ++it) { const Vector<UInt> & send_info = *it; send_array_per_proc[send_info(0)].push_back(send_info(1)); } for (auto & send_schemes : send_array_per_proc) { auto & scheme = communications.createSendScheme(send_schemes.first); auto & sends = send_schemes.second; std::sort(sends.begin(), sends.end()); std::transform(sends.begin(), sends.end(), sends.begin(), [this](UInt g) -> UInt { return mesh.getNodeLocalId(g); }); scheme.copy(sends); } } { // receive schemes const Array<NodeType> & nodes_type = this->getNodesType(); std::map<UInt, Array<UInt>> recv_array_per_proc; UInt node = 0; for (auto & node_type : nodes_type) { if (Int(node_type) >= 0) { recv_array_per_proc[node_type].push_back(mesh.getNodeGlobalId(node)); } ++node; } for (auto & recv_schemes : recv_array_per_proc) { auto & scheme = communications.createRecvScheme(recv_schemes.first); auto & recvs = recv_schemes.second; std::sort(recvs.begin(), recvs.end()); std::transform(recvs.begin(), recvs.end(), recvs.begin(), [this](UInt g) -> UInt { return mesh.getNodeLocalId(g); }); scheme.copy(recvs); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ MasterNodeInfoPerProc::MasterNodeInfoPerProc(NodeSynchronizer & synchronizer, UInt message_cnt, UInt root) : NodeInfoPerProc(synchronizer, message_cnt, root) { UInt nb_global_nodes = this->mesh.getNbGlobalNodes(); this->comm.broadcast(nb_global_nodes, this->root); } /* -------------------------------------------------------------------------- */ void MasterNodeInfoPerProc::synchronizeNodes() { this->nodes_per_proc.resize(nb_proc); this->nb_nodes_per_proc.resize(nb_proc); Array<Real> local_nodes(0, spatial_dimension); Array<Real> & nodes = this->getNodes(); for (UInt p = 0; p < nb_proc; ++p) { UInt nb_nodes = 0; // UInt * buffer; Array<Real> * nodes_to_send; Array<UInt> & nodespp = nodes_per_proc[p]; if (p != root) { nodes_to_send = new Array<Real>(0, spatial_dimension); AKANTU_DEBUG_INFO("Receiving number of nodes from proc " << p << " " << Tag::genTag(p, 0, Tag::_NB_NODES)); comm.receive(nb_nodes, p, Tag::genTag(p, 0, Tag::_NB_NODES)); nodespp.resize(nb_nodes); this->nb_nodes_per_proc(p) = nb_nodes; AKANTU_DEBUG_INFO("Receiving list of nodes from proc " << p << " " << Tag::genTag(p, 0, Tag::_NODES)); comm.receive(nodespp, p, Tag::genTag(p, 0, Tag::_NODES)); } else { Array<UInt> & local_ids = this->getNodesGlobalIds(); this->nb_nodes_per_proc(p) = local_ids.getSize(); nodespp.copy(local_ids); nodes_to_send = &local_nodes; } Array<UInt>::const_scalar_iterator it = nodespp.begin(); Array<UInt>::const_scalar_iterator end = nodespp.end(); /// get the coordinates for the selected nodes for (; it != end; ++it) { Vector<Real> coord(nodes.storage() + spatial_dimension * *it, spatial_dimension); nodes_to_send->push_back(coord); } if (p != root) { /// send them for distant processors AKANTU_DEBUG_INFO("Sending coordinates to proc " << p << " " << Tag::genTag(this->rank, 0, Tag::_COORDINATES)); comm.send(*nodes_to_send, p, Tag::genTag(this->rank, 0, Tag::_COORDINATES)); delete nodes_to_send; } } /// construct the local nodes coordinates nodes.copy(local_nodes); } /* -------------------------------------------------------------------------- */ void MasterNodeInfoPerProc::synchronizeTypes() { // <global_id, <proc, local_id> > std::multimap<UInt, std::pair<UInt, UInt>> nodes_to_proc; std::vector<Array<NodeType>> nodes_type_per_proc(nb_proc); // arrays containing pairs of (proc, node) std::vector<Array<UInt>> nodes_to_send_per_proc(nb_proc); for (UInt p = 0; p < nb_proc; ++p) { nodes_type_per_proc[p].resize(nb_nodes_per_proc(p)); } this->fillNodesType(); for (UInt p = 0; p < nb_proc; ++p) { auto & nodes_types = nodes_type_per_proc[p]; if (p != root) { AKANTU_DEBUG_INFO( "Receiving first nodes types from proc " << p << " " << Tag::genTag(this->rank, this->message_count, Tag::_NODES_TYPE)); comm.receive(nodes_types, p, Tag::genTag(p, 0, Tag::_NODES_TYPE)); } else { nodes_types.copy(this->getNodesType()); } // stack all processors claiming to be master for a node for (UInt local_node = 0; local_node < nb_nodes_per_proc(p); ++local_node) { if (nodes_types(local_node) == _nt_master) { UInt global_node = nodes_per_proc[p](local_node); nodes_to_proc.insert(std::make_pair(global_node, std::make_pair(p, local_node))); } } } for (UInt i = 0; i < mesh.getNbGlobalNodes(); ++i) { auto it_range = nodes_to_proc.equal_range(i); if (it_range.first == nodes_to_proc.end() || it_range.first->first != i) continue; // pick the first processor out of the multi-map as the actual master UInt master_proc = (it_range.first)->second.first; for (auto 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 != master_proc) { // store the info on all the slaves for a given master nodes_type_per_proc[proc](node) = NodeType(master_proc); nodes_to_send_per_proc[master_proc].push_back(proc); nodes_to_send_per_proc[master_proc].push_back(i); } } } std::vector<CommunicationRequest> requests_send_type; std::vector<CommunicationRequest> requests_send_master_info; for (UInt p = 0; p < nb_proc; ++p) { if (p != root) { AKANTU_DEBUG_INFO("Sending nodes types to proc " << p << " " << Tag::genTag(this->rank, 0, Tag::_NODES_TYPE)); requests_send_type.push_back( comm.asyncSend(nodes_type_per_proc[p], p, Tag::genTag(this->rank, 0, Tag::_NODES_TYPE))); auto & nodes_to_send = nodes_to_send_per_proc[p]; /// push back an element to avoid a send of size 0 nodes_to_send.push_back(-1); AKANTU_DEBUG_INFO("Sending nodes master info to proc " << p << " " << Tag::genTag(this->rank, 1, Tag::_NODES_TYPE)); requests_send_master_info.push_back( comm.asyncSend(nodes_to_send, p, Tag::genTag(this->rank, 1, Tag::_NODES_TYPE))); } else { this->getNodesType().copy(nodes_type_per_proc[p]); this->fillCommunicationScheme(nodes_to_send_per_proc[root]); } } comm.waitAll(requests_send_type); comm.freeCommunicationRequest(requests_send_type); requests_send_type.clear(); comm.waitAll(requests_send_master_info); comm.freeCommunicationRequest(requests_send_master_info); } /* -------------------------------------------------------------------------- */ void MasterNodeInfoPerProc::synchronizeGroups() { AKANTU_DEBUG_IN(); UInt nb_total_nodes = mesh.getNbGlobalNodes(); DynamicCommunicationBuffer buffer; typedef std::vector<std::vector<std::string>> NodeToGroup; NodeToGroup node_to_group; node_to_group.resize(nb_total_nodes); GroupManager::const_node_group_iterator ngi = mesh.node_group_begin(); GroupManager::const_node_group_iterator nge = mesh.node_group_end(); for (; ngi != nge; ++ngi) { NodeGroup & ng = *(ngi->second); std::string name = ngi->first; NodeGroup::const_node_iterator nit = ng.begin(); NodeGroup::const_node_iterator nend = ng.end(); for (; nit != nend; ++nit) { node_to_group[*nit].push_back(name); } nit = ng.begin(); if (nit != nend) ng.empty(); } buffer << node_to_group; std::vector<CommunicationRequest> requests; for (UInt p = 0; p < nb_proc; ++p) { if (p == this->rank) continue; AKANTU_DEBUG_INFO("Sending node groups to proc " << p << " " << Tag::genTag(this->rank, p, Tag::_NODE_GROUP)); requests.push_back(comm.asyncSend( buffer, p, Tag::genTag(this->rank, p, Tag::_NODE_GROUP))); } this->fillNodeGroupsFromBuffer(buffer); comm.waitAll(requests); comm.freeCommunicationRequest(requests); requests.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ SlaveNodeInfoPerProc::SlaveNodeInfoPerProc(NodeSynchronizer & synchronizer, UInt message_cnt, UInt root) : NodeInfoPerProc(synchronizer, message_cnt, root) { UInt nb_global_nodes = 0; comm.broadcast(nb_global_nodes, root); this->setNbGlobalNodes(nb_global_nodes); } /* -------------------------------------------------------------------------- */ void SlaveNodeInfoPerProc::synchronizeNodes() { AKANTU_DEBUG_INFO("Sending list of nodes to proc " << root << " " << Tag::genTag(this->rank, 0, Tag::_NB_NODES) << " " << Tag::genTag(this->rank, 0, Tag::_NODES)); Array<UInt> & local_ids = this->getNodesGlobalIds(); Array<Real> & nodes = this->getNodes(); UInt nb_nodes = local_ids.getSize(); comm.send(nb_nodes, root, Tag::genTag(this->rank, 0, Tag::_NB_NODES)); comm.send(local_ids, root, Tag::genTag(this->rank, 0, Tag::_NODES)); /* --------<<<<-COORDINATES---------------------------------------------- */ nodes.resize(nb_nodes); AKANTU_DEBUG_INFO("Receiving coordinates from proc " << root << " " << Tag::genTag(root, 0, Tag::_COORDINATES)); comm.receive(nodes, root, Tag::genTag(root, 0, Tag::_COORDINATES)); } /* -------------------------------------------------------------------------- */ void SlaveNodeInfoPerProc::synchronizeTypes() { this->fillNodesType(); Array<NodeType> & nodes_types = this->getNodesType(); AKANTU_DEBUG_INFO("Sending first nodes types to proc " << root << "" << Tag::genTag(this->rank, 0, Tag::_NODES_TYPE)); comm.send(nodes_types, root, Tag::genTag(this->rank, 0, Tag::_NODES_TYPE)); AKANTU_DEBUG_INFO("Receiving nodes types from proc " << root << " " << Tag::genTag(root, 0, Tag::_NODES_TYPE)); comm.receive(nodes_types, root, Tag::genTag(root, 0, Tag::_NODES_TYPE)); AKANTU_DEBUG_INFO("Receiving nodes master info from proc " << root << " " << Tag::genTag(root, 1, Tag::_NODES_TYPE)); CommunicationStatus status; comm.probe<UInt>(root, Tag::genTag(root, 1, Tag::_NODES_TYPE), status); Array<UInt> nodes_master_info(status.getSize()); comm.receive(nodes_master_info, root, Tag::genTag(root, 1, Tag::_NODES_TYPE)); nodes_master_info.resize(nodes_master_info.getSize() - 1); this->fillCommunicationScheme(nodes_master_info); } /* -------------------------------------------------------------------------- */ void SlaveNodeInfoPerProc::synchronizeGroups() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Receiving node groups from proc " << root << " " << Tag::genTag(root, this->rank, Tag::_NODE_GROUP)); CommunicationStatus status; comm.probe<char>(root, Tag::genTag(root, this->rank, Tag::_NODE_GROUP), status); CommunicationBuffer buffer(status.getSize()); comm.receive(buffer, root, Tag::genTag(root, this->rank, Tag::_NODE_GROUP)); this->fillNodeGroupsFromBuffer(buffer); AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +} // akantu diff --git a/src/synchronizer/node_info_per_processor.hh b/src/synchronizer/node_info_per_processor.hh index a3fe2ff0b..ca461d9d8 100644 --- a/src/synchronizer/node_info_per_processor.hh +++ b/src/synchronizer/node_info_per_processor.hh @@ -1,110 +1,110 @@ /** * @file node_info_per_processor.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Fri Mar 11 14:45:15 2016 * * @brief Helper classes to create the distributed synchronizer and distribute * 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "mesh_accessor.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NODE_INFO_PER_PROCESSOR_HH__ #define __AKANTU_NODE_INFO_PER_PROCESSOR_HH__ namespace akantu { class NodeSynchronizer; class StaticCommunicator; } /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class NodeInfoPerProc : protected MeshAccessor { public: NodeInfoPerProc(NodeSynchronizer & synchronizer, UInt message_cnt, UInt root); virtual void synchronizeNodes() = 0; virtual void synchronizeTypes() = 0; virtual void synchronizeGroups() = 0; protected: template <class CommunicationBuffer> void fillNodeGroupsFromBuffer(CommunicationBuffer & buffer); void fillNodesType(); void fillCommunicationScheme(const Array<UInt> &); protected: NodeSynchronizer & synchronizer; const StaticCommunicator & comm; UInt rank; UInt nb_proc; UInt root; Mesh & mesh; UInt spatial_dimension; UInt message_count; }; /* -------------------------------------------------------------------------- */ class MasterNodeInfoPerProc : protected NodeInfoPerProc { public: MasterNodeInfoPerProc(NodeSynchronizer & synchronizer, UInt message_cnt, UInt root); void synchronizeNodes(); void synchronizeTypes(); void synchronizeGroups(); private: /// get the list of nodes to send and send them std::vector<Array<UInt> > nodes_per_proc; Array<UInt> nb_nodes_per_proc; }; /* -------------------------------------------------------------------------- */ class SlaveNodeInfoPerProc : protected NodeInfoPerProc { public: SlaveNodeInfoPerProc(NodeSynchronizer & synchronizer, UInt message_cnt, UInt root); void synchronizeNodes(); void synchronizeTypes(); void synchronizeGroups(); private: }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_NODE_INFO_PER_PROCESSOR_HH__ */ diff --git a/src/synchronizer/real_static_communicator.hh b/src/synchronizer/real_static_communicator.hh index b974d12ca..ea35d9dc3 100644 --- a/src/synchronizer/real_static_communicator.hh +++ b/src/synchronizer/real_static_communicator.hh @@ -1,153 +1,153 @@ /** * @file real_static_communicator.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Jun 14 2010 * @date last modification: Wed Jan 13 2016 * * @brief empty class just for inheritance * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ #include <memory> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_REAL_STATIC_COMMUNICATOR_HH__ #define __AKANTU_REAL_STATIC_COMMUNICATOR_HH__ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ class InternalCommunicationRequest { public: InternalCommunicationRequest(UInt source, UInt dest); virtual ~InternalCommunicationRequest(); virtual void printself(std::ostream & stream, int indent = 0) const; AKANTU_GET_MACRO(Source, source, UInt); AKANTU_GET_MACRO(Destination, destination, UInt); private: UInt source; UInt destination; UInt id; static UInt counter; }; /* -------------------------------------------------------------------------- */ class CommunicationRequest { public: CommunicationRequest( std::shared_ptr<InternalCommunicationRequest> request = nullptr) : request(std::move(request)) {} // CommunicationRequest(CommunicationRequest & other) // : request(std::move(other.request)) {} // CommunicationRequest(CommunicationRequest && other) // : request(std::move(other.request)) {} // CommunicationRequest & operator=(CommunicationRequest & other) { // request = std::move(other.request); // return *this; // } // CommunicationRequest & operator=(CommunicationRequest && other) { // request = std::move(other.request); // return *this; // } virtual void free() { request.reset(); } void printself(std::ostream & stream, int indent = 0) const { request->printself(stream, indent); }; UInt getSource() const { return request->getSource(); } UInt getDestination() const { return request->getDestination(); } bool isFreed() const { return request.get() == nullptr; } InternalCommunicationRequest & getInternal() { return *request; } private: std::shared_ptr<InternalCommunicationRequest> request; }; /* -------------------------------------------------------------------------- */ class CommunicationStatus { public: CommunicationStatus() : source(0), size(0), tag(0){}; AKANTU_GET_MACRO(Source, source, Int); AKANTU_GET_MACRO(Size, size, UInt); AKANTU_GET_MACRO(Tag, tag, Int); AKANTU_SET_MACRO(Source, source, Int); AKANTU_SET_MACRO(Size, size, UInt); AKANTU_SET_MACRO(Tag, tag, Int); private: Int source; UInt size; Int tag; }; /* -------------------------------------------------------------------------- */ /// Datatype to pack pairs for MPI_{MIN,MAX}LOC template <typename T1, typename T2> struct SCMinMaxLoc { T1 min_max; T2 loc; }; /* -------------------------------------------------------------------------- */ class StaticCommunicator; /* -------------------------------------------------------------------------- */ class RealStaticCommunicator { public: RealStaticCommunicator(__attribute__((unused)) int & argc, __attribute__((unused)) char **& argv) { prank = -1; psize = -1; }; virtual ~RealStaticCommunicator(){}; friend class StaticCommunicator; Int getNbProc() { return this->psize; } Int whoAmI() { return this->prank; } protected: Int prank; Int psize; }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_REAL_STATIC_COMMUNICATOR_HH__ */ diff --git a/src/synchronizer/slave_element_info_per_processor.cc b/src/synchronizer/slave_element_info_per_processor.cc index 7263d6c36..78c764065 100644 --- a/src/synchronizer/slave_element_info_per_processor.cc +++ b/src/synchronizer/slave_element_info_per_processor.cc @@ -1,197 +1,197 @@ /** * @file slave_element_info_per_processor.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Fri Mar 11 14:59:21 2016 * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "element_info_per_processor.hh" #include "element_synchronizer.hh" #include "mesh_utils.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ #include <algorithm> #include <iostream> #include <map> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ SlaveElementInfoPerProc::SlaveElementInfoPerProc( ElementSynchronizer & synchronizer, UInt message_cnt, UInt root) : ElementInfoPerProc(synchronizer, message_cnt, root, _not_defined) { Vector<UInt> size(5); comm.receive(size, this->root, Tag::genTag(this->root, this->message_count, Tag::_SIZES)); this->type = (ElementType)size[0]; this->nb_local_element = size[1]; this->nb_ghost_element = size[2]; this->nb_element_to_receive = size[3]; this->nb_tags = size[4]; if (this->type != _not_defined) this->nb_nodes_per_element = Mesh::getNbNodesPerElement(type); } /* -------------------------------------------------------------------------- */ bool SlaveElementInfoPerProc::needSynchronize() { return this->type != _not_defined; } /* -------------------------------------------------------------------------- */ void SlaveElementInfoPerProc::synchronizeConnectivities() { Array<UInt> local_connectivity( (this->nb_local_element + this->nb_ghost_element) * this->nb_nodes_per_element); AKANTU_DEBUG_INFO("Receiving connectivities from proc " << root); comm.receive( local_connectivity, this->root, Tag::genTag(this->root, this->message_count, Tag::_CONNECTIVITY)); Array<UInt> & old_nodes = this->getNodesGlobalIds(); AKANTU_DEBUG_INFO("Renumbering local connectivities"); MeshUtils::renumberMeshNodes(this->mesh, local_connectivity, this->nb_local_element, this->nb_ghost_element, this->type, old_nodes); } /* -------------------------------------------------------------------------- */ void SlaveElementInfoPerProc::synchronizePartitions() { Array<UInt> local_partitions(this->nb_element_to_receive + this->nb_ghost_element * 2); AKANTU_DEBUG_INFO("Receiving partition informations from proc " << root); this->comm.receive(local_partitions, this->root, Tag::genTag(root, this->message_count, Tag::_PARTITIONS)); if (Mesh::getSpatialDimension(this->type) == this->mesh.getSpatialDimension()) { AKANTU_DEBUG_INFO("Creating communications scheme"); this->fillCommunicationScheme(local_partitions); } } /* -------------------------------------------------------------------------- */ void SlaveElementInfoPerProc::synchronizeTags() { AKANTU_DEBUG_IN(); if (this->nb_tags == 0) { AKANTU_DEBUG_OUT(); return; } /* --------<<<<-TAGS------------------------------------------------- */ UInt mesh_data_sizes_buffer_length = 0; CommunicationBuffer mesh_data_sizes_buffer; AKANTU_DEBUG_INFO( "Receiving the size of the information about the mesh data tags."); comm.broadcast(mesh_data_sizes_buffer_length, root); if (mesh_data_sizes_buffer_length != 0) { mesh_data_sizes_buffer.resize(mesh_data_sizes_buffer_length); AKANTU_DEBUG_INFO( "Receiving the information about the mesh data tags, addr " << (void *)mesh_data_sizes_buffer.storage()); comm.broadcast(mesh_data_sizes_buffer, root); AKANTU_DEBUG_INFO("Size of the information about the mesh data: " << mesh_data_sizes_buffer_length); std::vector<std::string> tag_names; std::vector<MeshDataTypeCode> tag_type_codes; std::vector<UInt> tag_nb_component; tag_names.resize(nb_tags); tag_type_codes.resize(nb_tags); tag_nb_component.resize(nb_tags); CommunicationBuffer mesh_data_buffer; UInt type_code_int; for (UInt i(0); i < nb_tags; ++i) { mesh_data_sizes_buffer >> tag_names[i]; mesh_data_sizes_buffer >> type_code_int; tag_type_codes[i] = static_cast<MeshDataTypeCode>(type_code_int); mesh_data_sizes_buffer >> tag_nb_component[i]; } std::vector<std::string>::const_iterator names_it = tag_names.begin(); std::vector<std::string>::const_iterator names_end = tag_names.end(); CommunicationStatus mesh_data_comm_status; AKANTU_DEBUG_INFO("Checking size of data to receive for mesh data TAG(" << Tag::genTag(root, this->message_count, Tag::_MESH_DATA) << ")"); comm.probe<char>(root, Tag::genTag(root, this->message_count, Tag::_MESH_DATA), mesh_data_comm_status); UInt mesh_data_buffer_size(mesh_data_comm_status.getSize()); AKANTU_DEBUG_INFO("Receiving " << mesh_data_buffer_size << " bytes of mesh data TAG(" << Tag::genTag(root, this->message_count, Tag::_MESH_DATA) << ")"); mesh_data_buffer.resize(mesh_data_buffer_size); comm.receive(mesh_data_buffer, root, Tag::genTag(root, this->message_count, Tag::_MESH_DATA)); // Loop over each tag for the current type UInt k(0); for (; names_it != names_end; ++names_it, ++k) { this->fillMeshData(mesh_data_buffer, *names_it, tag_type_codes[k], tag_nb_component[k]); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SlaveElementInfoPerProc::synchronizeGroups() { AKANTU_DEBUG_IN(); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); UInt my_rank = comm.whoAmI(); AKANTU_DEBUG_INFO("Receiving element groups from proc " << root << " TAG(" << Tag::genTag(root, my_rank, Tag::_ELEMENT_GROUP) << ")"); CommunicationStatus status; comm.probe<char>(root, Tag::genTag(root, my_rank, Tag::_ELEMENT_GROUP), status); CommunicationBuffer buffer(status.getSize()); comm.receive(buffer, root, Tag::genTag(root, my_rank, Tag::_ELEMENT_GROUP)); this->fillElementGroupsFromBuffer(buffer); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -__END_AKANTU__ +} // akantu diff --git a/src/synchronizer/static_communicator.cc b/src/synchronizer/static_communicator.cc index 89f93e134..501e94347 100644 --- a/src/synchronizer/static_communicator.cc +++ b/src/synchronizer/static_communicator.cc @@ -1,133 +1,133 @@ /** * @file static_communicator.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Jan 19 2016 * * @brief implementation of the common part of the static communicator * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "static_communicator.hh" #include "static_communicator_dummy.hh" #ifdef AKANTU_USE_MPI #include "static_communicator_mpi.hh" #endif /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ bool StaticCommunicator::is_instantiated = false; StaticCommunicator * StaticCommunicator::static_communicator = NULL; UInt InternalCommunicationRequest::counter = 0; /* -------------------------------------------------------------------------- */ InternalCommunicationRequest::InternalCommunicationRequest(UInt source, UInt dest) : source(source), destination(dest) { this->id = counter++; } /* -------------------------------------------------------------------------- */ InternalCommunicationRequest::~InternalCommunicationRequest() {} /* -------------------------------------------------------------------------- */ void InternalCommunicationRequest::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "CommunicationRequest [" << std::endl; stream << space << " + id : " << id << std::endl; stream << space << " + source : " << source << std::endl; stream << space << " + destination : " << destination << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ StaticCommunicator::StaticCommunicator(int & argc, char **& argv, CommunicatorType type) { real_type = type; #ifdef AKANTU_USE_MPI if (type == _communicator_mpi) { real_static_communicator = new StaticCommunicatorMPI(argc, argv); } else { #endif real_static_communicator = new StaticCommunicatorDummy(argc, argv); #ifdef AKANTU_USE_MPI } #endif this->is_instantiated = true; } /* -------------------------------------------------------------------------- */ StaticCommunicator::~StaticCommunicator() { FinalizeCommunicatorEvent * event = new FinalizeCommunicatorEvent(*this); this->sendEvent(*event); this->barrier(); delete event; delete real_static_communicator; is_instantiated = false; StaticCommunicator::static_communicator = NULL; } /* -------------------------------------------------------------------------- */ StaticCommunicator & StaticCommunicator::getStaticCommunicator(CommunicatorType type) { AKANTU_DEBUG_IN(); if (!static_communicator) { int nb_args = 0; char ** null; static_communicator = new StaticCommunicator(nb_args, null, type); } AKANTU_DEBUG_OUT(); return *static_communicator; } /* -------------------------------------------------------------------------- */ StaticCommunicator & StaticCommunicator::getStaticCommunicator(int & argc, char **& argv, CommunicatorType type) { if (!static_communicator) static_communicator = new StaticCommunicator(argc, argv, type); return getStaticCommunicator(type); } /* -------------------------------------------------------------------------- */ StaticCommunicator * StaticCommunicator::getStaticCommunicatorDummy() { int nb_args = 0; char ** null; return new StaticCommunicator(nb_args, null, _communicator_dummy); } -__END_AKANTU__ +} // akantu diff --git a/src/synchronizer/static_communicator.hh b/src/synchronizer/static_communicator.hh index 484b97adb..a1307f1fb 100644 --- a/src/synchronizer/static_communicator.hh +++ b/src/synchronizer/static_communicator.hh @@ -1,417 +1,417 @@ /** * @file static_communicator.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Jan 19 2016 * * @brief Class handling the parallel communications * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_STATIC_COMMUNICATOR_HH__ #define __AKANTU_STATIC_COMMUNICATOR_HH__ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" #include "aka_common.hh" #include "aka_event_handler_manager.hh" #include "communication_buffer.hh" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #define AKANTU_COMMUNICATOR_LIST_0 BOOST_PP_SEQ_NIL #include "static_communicator_dummy.hh" #define AKANTU_COMMUNICATOR_LIST_1 \ BOOST_PP_SEQ_PUSH_BACK( \ AKANTU_COMMUNICATOR_LIST_0, \ (_communicator_dummy, (StaticCommunicatorDummy, BOOST_PP_NIL))) #if defined(AKANTU_USE_MPI) #include "static_communicator_mpi.hh" #define AKANTU_COMMUNICATOR_LIST_ALL \ BOOST_PP_SEQ_PUSH_BACK( \ AKANTU_COMMUNICATOR_LIST_1, \ (_communicator_mpi, (StaticCommunicatorMPI, BOOST_PP_NIL))) #else #define AKANTU_COMMUNICATOR_LIST_ALL AKANTU_COMMUNICATOR_LIST_1 #endif // AKANTU_COMMUNICATOR_LIST #include "real_static_communicator.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class RealStaticCommunicator; struct FinalizeCommunicatorEvent { explicit FinalizeCommunicatorEvent(const StaticCommunicator & comm) : communicator(comm) {} const StaticCommunicator & communicator; }; class CommunicatorEventHandler { public: virtual ~CommunicatorEventHandler() {} virtual void onCommunicatorFinalize() { } private: inline void sendEvent(const FinalizeCommunicatorEvent &) { onCommunicatorFinalize(); } template <class EventHandler> friend class EventHandlerManager; }; class StaticCommunicator : public EventHandlerManager<CommunicatorEventHandler> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ protected: StaticCommunicator(int & argc, char **& argv, CommunicatorType type = _communicator_mpi); public: virtual ~StaticCommunicator(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Point to Point */ /* ------------------------------------------------------------------------ */ template <typename T> inline void receive(Array<T> & values, Int sender, Int tag) const { return this->receive(values.storage(), values.getSize() * values.getNbComponent(), sender, tag); } template <typename T> inline void receive(Vector<T> & values, Int sender, Int tag) const { return this->receive(values.storage(), values.size(), sender, tag); } template <typename T> inline void receive(Matrix<T> & values, Int sender, Int tag) const { return this->receive(values.storage(), values.size(), sender, tag); } template <bool is_static> inline void receive(CommunicationBufferTemplated<is_static> & values, Int sender, Int tag) const { return this->receive(values.storage(), values.getSize(), sender, tag); } template <typename T> inline void receive(T & values, Int sender, Int tag) const { return this->receive(&values, 1, sender, tag); } /* ------------------------------------------------------------------------ */ template <typename T> inline void send(Array<T> & values, Int receiver, Int tag) const { return this->send(values.storage(), values.getSize() * values.getNbComponent(), receiver, tag); } template <typename T> inline void send(Vector<T> & values, Int receiver, Int tag) const { return this->send(values.storage(), values.size(), receiver, tag); } template <typename T> inline void send(Matrix<T> & values, Int receiver, Int tag) const { return this->send(values.storage(), values.size(), receiver, tag); } template <bool is_static> inline void send(CommunicationBufferTemplated<is_static> & values, Int receiver, Int tag) const { return this->send(values.storage(), values.getSize(), receiver, tag); } template <typename T> inline void send(T & values, Int receiver, Int tag) const { return this->send(&values, 1, receiver, tag); } /* ------------------------------------------------------------------------ */ template <typename T> inline CommunicationRequest asyncSend(Array<T> & values, Int receiver, Int tag) const { return this->asyncSend(values.storage(), values.getSize() * values.getNbComponent(), receiver, tag); } template <typename T> inline CommunicationRequest asyncSend(Vector<T> & values, Int receiver, Int tag) const { return this->asyncSend(values.storage(), values.size(), receiver, tag); } template <typename T> inline CommunicationRequest asyncSend(Matrix<T> & values, Int receiver, Int tag) const { return this->asyncSend(values.storage(), values.size(), receiver, tag); } template <bool is_static> inline CommunicationRequest asyncSend(CommunicationBufferTemplated<is_static> & values, Int receiver, Int tag) const { return this->asyncSend(values.storage(), values.getSize(), receiver, tag); } template <typename T> inline CommunicationRequest asyncSend(T & values, Int receiver, Int tag) const { return this->asyncSend(&values, 1, receiver, tag); } /* ------------------------------------------------------------------------ */ template <typename T> inline CommunicationRequest asyncReceive(Array<T> & values, Int sender, Int tag) const { return this->asyncReceive(values.storage(), values.getSize() * values.getNbComponent(), sender, tag); } template <typename T, UInt ndim, class RetType> inline CommunicationRequest asyncReceive(TensorStorage<T, ndim, RetType> & values, Int sender, Int tag) const { return this->asyncReceive(values.storage(), values.size(), sender, tag); } template <bool is_static> inline CommunicationRequest asyncReceive(CommunicationBufferTemplated<is_static> & values, Int sender, Int tag) const { return this->asyncReceive(values.storage(), values.getSize(), sender, tag); } /* ------------------------------------------------------------------------ */ template <typename T> inline void probe(Int sender, Int tag, CommunicationStatus & status) const; /* ------------------------------------------------------------------------ */ /* Collectives */ /* ------------------------------------------------------------------------ */ template <typename T> inline void allReduce(Array<T> & values, const SynchronizerOperation & op) const { this->allReduce(values.storage(), values.getSize() * values.getNbComponent(), op); } template <typename T> inline void allReduce(Vector<T> & values, const SynchronizerOperation & op) const { this->allReduce(values.storage(), values.size(), op); } template <typename T> inline void allReduce(Matrix<T> & values, const SynchronizerOperation & op) const { this->allReduce(values.storage(), values.size(), op); } template <typename T> inline void allReduce(T & values, const SynchronizerOperation & op) const { this->allReduce(&values, 1, op); } /* ------------------------------------------------------------------------ */ template <typename T> inline void allGather(Array<T> & values) const { AKANTU_DEBUG_ASSERT(UInt(this->real_static_communicator->getNbProc()) == values.getSize(), "The array size is not correct"); this->allGather(values.storage(), values.getNbComponent()); } template <typename T> inline void allGather(Vector<T> & values) const { AKANTU_DEBUG_ASSERT(UInt(this->real_static_communicator->getNbProc()) == values.size(), "The array size is not correct"); this->allGather(values.storage(), 1); } /* ------------------------------------------------------------------------ */ template <typename T> inline void allGatherV(Array<T> & values, Array<Int> sizes) const { this->allGatherV(values.storage(), sizes.storage()); } /* ------------------------------------------------------------------------ */ template <typename T> inline void reduce(Array<T> & values, const SynchronizerOperation & op, int root = 0) const { this->reduce(values.storage(), values.getSize() * values.getNbComponent(), op, root); } /* ------------------------------------------------------------------------ */ template <typename T> inline void gather(Vector<T> & values, int root = 0) const { this->gather(values.storage(), values.getNbComponent(), root); } template <typename T> inline void gather(T values, int root = 0) const { this->gather(&values, 1, root); } /* ------------------------------------------------------------------------ */ template <typename T> inline void gather(Vector<T> & values, Array<T> & gathered) const { AKANTU_DEBUG_ASSERT(values.getSize() == gathered.getNbComponent(), "The array size is not correct"); gathered.resize(this->real_static_communicator->getNbProc()); this->gather(values.data(), values.getSize(), gathered.storage(), gathered.getNbComponent()); } template <typename T> inline void gather(T values, Array<T> & gathered) const { this->gather(&values, 1, gathered.storage(), 1); } /* ------------------------------------------------------------------------ */ template <typename T> inline void gatherV(Array<T> & values, Array<Int> sizes, int root = 0) const { this->gatherV(values.storage(), sizes.storage(), root); } /* ------------------------------------------------------------------------ */ template <typename T> inline void broadcast(Array<T> & values, int root = 0) const { this->broadcast(values.storage(), values.getSize() * values.getNbComponent(), root); } template <bool is_static> inline void broadcast(CommunicationBufferTemplated<is_static> & values, int root = 0) const { this->broadcast(values.storage(), values.getSize(), root); } template <typename T> inline void broadcast(T & values, int root = 0) const { this->broadcast(&values, 1, root); } /* ------------------------------------------------------------------------ */ inline void barrier() const; /* ------------------------------------------------------------------------ */ /* Request handling */ /* ------------------------------------------------------------------------ */ inline bool testRequest(CommunicationRequest & request) const; inline void wait(CommunicationRequest & request) const; inline void waitAll(std::vector<CommunicationRequest> & requests) const; inline UInt waitAny(std::vector<CommunicationRequest> & requests) const; inline void freeCommunicationRequest(CommunicationRequest & request) const; inline void freeCommunicationRequest(std::vector<CommunicationRequest> & requests) const; protected: template <typename T> inline void send(T * buffer, Int size, Int receiver, Int tag) const; template <typename T> inline void receive(T * buffer, Int size, Int sender, Int tag) const; template <typename T> inline CommunicationRequest asyncSend(T * buffer, Int size, Int receiver, Int tag) const; template <typename T> inline CommunicationRequest asyncReceive(T * buffer, Int size, Int sender, Int tag) const; template <typename T> inline void allReduce(T * values, int nb_values, const SynchronizerOperation & op) const; template <typename T> inline void allGather(T * values, int nb_values) const; template <typename T> inline void allGatherV(T * values, int * nb_values) const; template <typename T> inline void reduce(T * values, int nb_values, const SynchronizerOperation & op, int root = 0) const; template <typename T> inline void gather(T * values, int nb_values, int root = 0) const; template <typename T> inline void gather(T * values, int nb_values, T * gathered, int nb_gathered = 0) const; template <typename T> inline void gatherV(T * values, int * nb_values, int root = 0) const; template <typename T> inline void broadcast(T * values, int nb_values, int root = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: virtual Int getNbProc() const { return real_static_communicator->psize; }; virtual Int whoAmI() const { return real_static_communicator->prank; }; AKANTU_GET_MACRO(RealStaticCommunicator, *real_static_communicator, const RealStaticCommunicator &); AKANTU_GET_MACRO_NOT_CONST(RealStaticCommunicator, *real_static_communicator, RealStaticCommunicator &); template <class Comm> Comm & getRealStaticCommunicator() { return dynamic_cast<Comm &>(*real_static_communicator); } static StaticCommunicator & getStaticCommunicator(CommunicatorType type = _communicator_mpi); static StaticCommunicator & getStaticCommunicator(int & argc, char **& argv, CommunicatorType type = _communicator_mpi); static StaticCommunicator * getStaticCommunicatorDummy(); static bool isInstantiated() { return is_instantiated; }; int getMaxTag() const; int getMinTag() const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: static bool is_instantiated; static StaticCommunicator * static_communicator; RealStaticCommunicator * real_static_communicator; CommunicatorType real_type; }; /* -------------------------------------------------------------------------- */ /* Inline Functions ArrayBase */ /* -------------------------------------------------------------------------- */ inline std::ostream & operator<<(std::ostream & stream, const CommunicationRequest & _this) { _this.printself(stream); return stream; } -__END_AKANTU__ +} // akantu #include "static_communicator_inline_impl.hh" #endif /* __AKANTU_STATIC_COMMUNICATOR_HH__ */ diff --git a/src/synchronizer/static_communicator_dummy.hh b/src/synchronizer/static_communicator_dummy.hh index cc5748c2f..2e99950ec 100644 --- a/src/synchronizer/static_communicator_dummy.hh +++ b/src/synchronizer/static_communicator_dummy.hh @@ -1,122 +1,122 @@ /** * @file static_communicator_dummy.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Wed Jan 13 2016 * * @brief Dummy communicator to make everything work im sequential * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_STATIC_COMMUNICATOR_DUMMY_HH__ #define __AKANTU_STATIC_COMMUNICATOR_DUMMY_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "real_static_communicator.hh" /* -------------------------------------------------------------------------- */ #include <cstring> #include <vector> /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { class StaticCommunicatorDummy : public RealStaticCommunicator { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: StaticCommunicatorDummy(int & argc, char **& argv) : RealStaticCommunicator(argc, argv) { this->prank = 0; this->psize = 1; } virtual ~StaticCommunicatorDummy() {} /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: template <typename T> void send(T *, Int, Int, Int) {} template <typename T> void receive(T *, Int, Int, Int) {} template <typename T> CommunicationRequest asyncSend(T *, Int, Int, Int) { return std::shared_ptr<InternalCommunicationRequest>( new InternalCommunicationRequest(0, 0)); } template <typename T> CommunicationRequest asyncReceive(T *, Int, Int, Int) { return std::shared_ptr<InternalCommunicationRequest>( new InternalCommunicationRequest(0, 0)); } template <typename T> inline void probe(Int, Int, CommunicationStatus &) {} bool testRequest(CommunicationRequest &) { return true; } void wait(CommunicationRequest &) {} void waitAll(std::vector<CommunicationRequest> &) {} UInt waitAny(std::vector<CommunicationRequest> &) { return UInt(-1); } void barrier() {} template <typename T> void reduce(T *, int, const SynchronizerOperation &, int) {} template <typename T> void allReduce(T *, int, const SynchronizerOperation &) {} template <typename T> inline void allGather(T *, int) {} template <typename T> inline void allGatherV(T *, int *) {} template <typename T> inline void gather(T *, int, int = 0) {} template <typename T> inline void gather(T * values, int nb_values, T * gathered, int) { std::memcpy(gathered, values, nb_values); } template <typename T> inline void gatherV(T *, int *, int = 0) {} template <typename T> inline void broadcast(T *, int, int = 0) {} /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ int getMaxTag() { return std::numeric_limits<int>::max(); } int getMinTag() { return 0; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ }; -__END_AKANTU__ +} // akantu #endif /* __AKANTU_STATIC_COMMUNICATOR_DUMMY_HH__ */ diff --git a/src/synchronizer/static_communicator_mpi.cc b/src/synchronizer/static_communicator_mpi.cc index af1f5a636..fb931b9d7 100644 --- a/src/synchronizer/static_communicator_mpi.cc +++ b/src/synchronizer/static_communicator_mpi.cc @@ -1,557 +1,557 @@ /** * @file static_communicator_mpi.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sun Sep 26 2010 * @date last modification: Thu Jan 21 2016 * * @brief StaticCommunicatorMPI implementation * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <iostream> /* -------------------------------------------------------------------------- */ #include "mpi_type_wrapper.hh" #include "static_communicator_mpi.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { MPI_Op MPITypeWrapper::synchronizer_operation_to_mpi_op[_so_null + 1] = { MPI_SUM, MPI_MIN, MPI_MAX, MPI_PROD, MPI_LAND, MPI_BAND, MPI_LOR, MPI_BOR, MPI_LXOR, MPI_BXOR, MPI_MINLOC, MPI_MAXLOC, MPI_OP_NULL}; class CommunicationRequestMPI : public InternalCommunicationRequest { public: CommunicationRequestMPI(UInt source, UInt dest); MPI_Request & getMPIRequest() { return *request; }; private: std::unique_ptr<MPI_Request> request; }; /* -------------------------------------------------------------------------- */ /* Implementation */ /* -------------------------------------------------------------------------- */ CommunicationRequestMPI::CommunicationRequestMPI(UInt source, UInt dest) : InternalCommunicationRequest(source, dest), request(new MPI_Request) {} /* -------------------------------------------------------------------------- */ StaticCommunicatorMPI::StaticCommunicatorMPI(int & argc, char **& argv) : RealStaticCommunicator(argc, argv) { int is_initialized = false; MPI_Initialized(&is_initialized); if (!is_initialized) { MPI_Init(&argc, &argv); } this->is_externaly_initialized = is_initialized; mpi_data = new MPITypeWrapper(*this); mpi_data->setMPICommunicator(MPI_COMM_WORLD); } /* -------------------------------------------------------------------------- */ StaticCommunicatorMPI::~StaticCommunicatorMPI() { if (!this->is_externaly_initialized) { MPI_Finalize(); delete this->mpi_data; } } /* -------------------------------------------------------------------------- */ template <typename T> void StaticCommunicatorMPI::send(T * buffer, Int size, Int receiver, Int tag) { MPI_Comm communicator = mpi_data->getMPICommunicator(); MPI_Datatype type = MPITypeWrapper::getMPIDatatype<T>(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Send(buffer, size, type, receiver, tag, communicator); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Send."); } /* -------------------------------------------------------------------------- */ template <typename T> void StaticCommunicatorMPI::receive(T * buffer, Int size, Int sender, Int tag) { MPI_Comm communicator = mpi_data->getMPICommunicator(); MPI_Status status; MPI_Datatype type = MPITypeWrapper::getMPIDatatype<T>(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Recv(buffer, size, type, sender, tag, communicator, &status); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Recv."); } /* -------------------------------------------------------------------------- */ template <typename T> CommunicationRequest StaticCommunicatorMPI::asyncSend(T * buffer, Int size, Int receiver, Int tag) { MPI_Comm communicator = mpi_data->getMPICommunicator(); CommunicationRequestMPI * request = new CommunicationRequestMPI(prank, receiver); MPI_Datatype type = MPITypeWrapper::getMPIDatatype<T>(); MPI_Request & req = request->getMPIRequest(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Isend(buffer, size, type, receiver, tag, communicator, &req); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Isend."); return std::shared_ptr<InternalCommunicationRequest>(request); } /* -------------------------------------------------------------------------- */ template <typename T> CommunicationRequest StaticCommunicatorMPI::asyncReceive(T * buffer, Int size, Int sender, Int tag) { MPI_Comm communicator = mpi_data->getMPICommunicator(); CommunicationRequestMPI * request = new CommunicationRequestMPI(sender, prank); MPI_Datatype type = MPITypeWrapper::getMPIDatatype<T>(); MPI_Request & req = request->getMPIRequest(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Irecv(buffer, size, type, sender, tag, communicator, &req); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Irecv."); return std::shared_ptr<InternalCommunicationRequest>(request); } /* -------------------------------------------------------------------------- */ template <typename T> void StaticCommunicatorMPI::probe(Int sender, Int tag, CommunicationStatus & status) { MPI_Comm communicator = mpi_data->getMPICommunicator(); MPI_Status mpi_status; #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Probe(sender, tag, communicator, &mpi_status); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Probe."); MPI_Datatype type = MPITypeWrapper::getMPIDatatype<T>(); int count; MPI_Get_count(&mpi_status, type, &count); status.setSource(mpi_status.MPI_SOURCE); status.setTag(mpi_status.MPI_TAG); status.setSize(count); } /* -------------------------------------------------------------------------- */ bool StaticCommunicatorMPI::testRequest(CommunicationRequest & request) { MPI_Status status; int flag; CommunicationRequestMPI & req_mpi = dynamic_cast<CommunicationRequestMPI &>(request.getInternal()); MPI_Request & req = req_mpi.getMPIRequest(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Test(&req, &flag, &status); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Test."); return (flag != 0); } /* -------------------------------------------------------------------------- */ void StaticCommunicatorMPI::wait(CommunicationRequest & request) { MPI_Status status; CommunicationRequestMPI & req_mpi = dynamic_cast<CommunicationRequestMPI &>(request.getInternal()); MPI_Request & req = req_mpi.getMPIRequest(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Wait(&req, &status); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Wait."); } /* -------------------------------------------------------------------------- */ void StaticCommunicatorMPI::waitAll( std::vector<CommunicationRequest> & requests) { MPI_Status status; std::vector<CommunicationRequest>::iterator it; for (it = requests.begin(); it != requests.end(); ++it) { MPI_Request & req = dynamic_cast<CommunicationRequestMPI &>(it->getInternal()) .getMPIRequest(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Wait(&req, &status); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Wait."); } } /* -------------------------------------------------------------------------- */ UInt StaticCommunicatorMPI::waitAny( std::vector<CommunicationRequest> & requests) { MPI_Status status; std::vector<MPI_Request> reqs(requests.size()); UInt r = 0; for (auto it = requests.begin(); it != requests.end(); ++it, ++r) { reqs[r] = static_cast<CommunicationRequestMPI *>(&it->getInternal()) ->getMPIRequest(); } int pos; #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Waitany(requests.size(), reqs.data(), &pos, &status); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Wait."); if (pos != MPI_UNDEFINED) { return pos; } else { return UInt(-1); } } /* -------------------------------------------------------------------------- */ void StaticCommunicatorMPI::barrier() { MPI_Comm communicator = mpi_data->getMPICommunicator(); MPI_Barrier(communicator); } /* -------------------------------------------------------------------------- */ template <typename T> void StaticCommunicatorMPI::reduce(T * values, int nb_values, const SynchronizerOperation & op, int root) { MPI_Comm communicator = mpi_data->getMPICommunicator(); MPI_Datatype type = MPITypeWrapper::getMPIDatatype<T>(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Reduce(MPI_IN_PLACE, values, nb_values, type, MPITypeWrapper::getMPISynchronizerOperation(op), root, communicator); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Allreduce."); } /* -------------------------------------------------------------------------- */ template <typename T> void StaticCommunicatorMPI::allReduce(T * values, int nb_values, const SynchronizerOperation & op) { MPI_Comm communicator = mpi_data->getMPICommunicator(); MPI_Datatype type = MPITypeWrapper::getMPIDatatype<T>(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Allreduce(MPI_IN_PLACE, values, nb_values, type, MPITypeWrapper::getMPISynchronizerOperation(op), communicator); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Allreduce."); } /* -------------------------------------------------------------------------- */ template <typename T> void StaticCommunicatorMPI::allGather(T * values, int nb_values) { MPI_Comm communicator = mpi_data->getMPICommunicator(); MPI_Datatype type = MPITypeWrapper::getMPIDatatype<T>(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Allgather(MPI_IN_PLACE, nb_values, type, values, nb_values, type, communicator); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Allgather."); } /* -------------------------------------------------------------------------- */ template <typename T> void StaticCommunicatorMPI::allGatherV(T * values, int * nb_values) { MPI_Comm communicator = mpi_data->getMPICommunicator(); int * displs = new int[psize]; displs[0] = 0; for (int i = 1; i < psize; ++i) { displs[i] = displs[i - 1] + nb_values[i - 1]; } MPI_Datatype type = MPITypeWrapper::getMPIDatatype<T>(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Allgatherv(MPI_IN_PLACE, *nb_values, type, values, nb_values, displs, type, communicator); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Gather."); delete[] displs; } /* -------------------------------------------------------------------------- */ template <typename T> void StaticCommunicatorMPI::gather(T * values, int nb_values, int root) { MPI_Comm communicator = mpi_data->getMPICommunicator(); T *send_buf = NULL, *recv_buf = NULL; if (prank == root) { send_buf = (T *)MPI_IN_PLACE; recv_buf = values; } else { send_buf = values; } MPI_Datatype type = MPITypeWrapper::getMPIDatatype<T>(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Gather(send_buf, nb_values, type, recv_buf, nb_values, type, root, communicator); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Gather."); } /* -------------------------------------------------------------------------- */ template <typename T> void StaticCommunicatorMPI::gather(T * values, int nb_values, T * gathered, int nb_gathered) { MPI_Comm communicator = mpi_data->getMPICommunicator(); T * send_buf = values; T * recv_buf = gathered; if (nb_gathered == 0) nb_gathered = nb_values; MPI_Datatype type = MPITypeWrapper::getMPIDatatype<T>(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Gather(send_buf, nb_values, type, recv_buf, nb_gathered, type, this->prank, communicator); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Gather."); } /* -------------------------------------------------------------------------- */ template <typename T> void StaticCommunicatorMPI::gatherV(T * values, int * nb_values, int root) { MPI_Comm communicator = mpi_data->getMPICommunicator(); int * displs = NULL; if (prank == root) { displs = new int[psize]; displs[0] = 0; for (int i = 1; i < psize; ++i) { displs[i] = displs[i - 1] + nb_values[i - 1]; } } T *send_buf = NULL, *recv_buf = NULL; if (prank == root) { send_buf = (T *)MPI_IN_PLACE; recv_buf = values; } else send_buf = values; MPI_Datatype type = MPITypeWrapper::getMPIDatatype<T>(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Gatherv(send_buf, *nb_values, type, recv_buf, nb_values, displs, type, root, communicator); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Gather."); if (prank == root) { delete[] displs; } } /* -------------------------------------------------------------------------- */ template <typename T> void StaticCommunicatorMPI::broadcast(T * values, int nb_values, int root) { MPI_Comm communicator = mpi_data->getMPICommunicator(); MPI_Datatype type = MPITypeWrapper::getMPIDatatype<T>(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Bcast(values, nb_values, type, root, communicator); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Gather."); } /* -------------------------------------------------------------------------- */ int StaticCommunicatorMPI::getMaxTag() { return this->mpi_data->getMaxTag(); } /* -------------------------------------------------------------------------- */ int StaticCommunicatorMPI::getMinTag() { return 0; } /* -------------------------------------------------------------------------- */ // template<typename T> // MPI_Datatype StaticCommunicatorMPI::getMPIDatatype() { // return MPI_DATATYPE_NULL; // } template <> MPI_Datatype MPITypeWrapper::getMPIDatatype<char>() { return MPI_CHAR; } template <> MPI_Datatype MPITypeWrapper::getMPIDatatype<float>() { return MPI_FLOAT; } template <> MPI_Datatype MPITypeWrapper::getMPIDatatype<double>() { return MPI_DOUBLE; } template <> MPI_Datatype MPITypeWrapper::getMPIDatatype<long double>() { return MPI_LONG_DOUBLE; } template <> MPI_Datatype MPITypeWrapper::getMPIDatatype<signed int>() { return MPI_INT; } template <> MPI_Datatype MPITypeWrapper::getMPIDatatype<NodeType>() { return MPITypeWrapper::getMPIDatatype<Int>(); } template <> MPI_Datatype MPITypeWrapper::getMPIDatatype<unsigned int>() { return MPI_UNSIGNED; } template <> MPI_Datatype MPITypeWrapper::getMPIDatatype<signed long int>() { return MPI_LONG; } template <> MPI_Datatype MPITypeWrapper::getMPIDatatype<unsigned long int>() { return MPI_UNSIGNED_LONG; } template <> MPI_Datatype MPITypeWrapper::getMPIDatatype<signed long long int>() { return MPI_LONG_LONG; } template <> MPI_Datatype MPITypeWrapper::getMPIDatatype<unsigned long long int>() { return MPI_UNSIGNED_LONG_LONG; } template <> MPI_Datatype MPITypeWrapper::getMPIDatatype<SCMinMaxLoc<double, int>>() { return MPI_DOUBLE_INT; } template <> MPI_Datatype MPITypeWrapper::getMPIDatatype<SCMinMaxLoc<float, int>>() { return MPI_FLOAT_INT; } template <> MPI_Datatype MPITypeWrapper::getMPIDatatype<bool>() { return MPI_CXX_BOOL; } /* -------------------------------------------------------------------------- */ /* Template instantiation */ /* -------------------------------------------------------------------------- */ #define AKANTU_MPI_COMM_INSTANTIATE(T) \ template void StaticCommunicatorMPI::send<T>(T * buffer, Int size, \ Int receiver, Int tag); \ template void StaticCommunicatorMPI::receive<T>(T * buffer, Int size, \ Int sender, Int tag); \ template CommunicationRequest StaticCommunicatorMPI::asyncSend<T>( \ T * buffer, Int size, Int receiver, Int tag); \ template CommunicationRequest StaticCommunicatorMPI::asyncReceive<T>( \ T * buffer, Int size, Int sender, Int tag); \ template void StaticCommunicatorMPI::probe<T>(Int sender, Int tag, \ CommunicationStatus & status); \ template void StaticCommunicatorMPI::allGather<T>(T * values, \ int nb_values); \ template void StaticCommunicatorMPI::allGatherV<T>(T * values, \ int * nb_values); \ template void StaticCommunicatorMPI::gather<T>(T * values, int nb_values, \ int root); \ template void StaticCommunicatorMPI::gather<T>( \ T * values, int nb_values, T * gathered, int nb_gathered); \ template void StaticCommunicatorMPI::gatherV<T>(T * values, int * nb_values, \ int root); \ template void StaticCommunicatorMPI::broadcast<T>(T * values, int nb_values, \ int root); \ template void StaticCommunicatorMPI::allReduce<T>( \ T * values, int nb_values, const SynchronizerOperation & op) AKANTU_MPI_COMM_INSTANTIATE(bool); AKANTU_MPI_COMM_INSTANTIATE(Real); AKANTU_MPI_COMM_INSTANTIATE(UInt); AKANTU_MPI_COMM_INSTANTIATE(Int); AKANTU_MPI_COMM_INSTANTIATE(char); AKANTU_MPI_COMM_INSTANTIATE(NodeType); template void StaticCommunicatorMPI::send<SCMinMaxLoc<Real, int>>( SCMinMaxLoc<Real, int> * buffer, Int size, Int receiver, Int tag); template void StaticCommunicatorMPI::receive<SCMinMaxLoc<Real, int>>( SCMinMaxLoc<Real, int> * buffer, Int size, Int sender, Int tag); template CommunicationRequest StaticCommunicatorMPI::asyncSend<SCMinMaxLoc<Real, int>>( SCMinMaxLoc<Real, int> * buffer, Int size, Int receiver, Int tag); template CommunicationRequest StaticCommunicatorMPI::asyncReceive<SCMinMaxLoc<Real, int>>( SCMinMaxLoc<Real, int> * buffer, Int size, Int sender, Int tag); template void StaticCommunicatorMPI::probe<SCMinMaxLoc<Real, int>>( Int sender, Int tag, CommunicationStatus & status); template void StaticCommunicatorMPI::allGather<SCMinMaxLoc<Real, int>>( SCMinMaxLoc<Real, int> * values, int nb_values); template void StaticCommunicatorMPI::allGatherV<SCMinMaxLoc<Real, int>>( SCMinMaxLoc<Real, int> * values, int * nb_values); template void StaticCommunicatorMPI::gather<SCMinMaxLoc<Real, int>>( SCMinMaxLoc<Real, int> * values, int nb_values, int root); template void StaticCommunicatorMPI::gatherV<SCMinMaxLoc<Real, int>>( SCMinMaxLoc<Real, int> * values, int * nb_values, int root); template void StaticCommunicatorMPI::broadcast<SCMinMaxLoc<Real, int>>( SCMinMaxLoc<Real, int> * values, int nb_values, int root); template void StaticCommunicatorMPI::allReduce<SCMinMaxLoc<Real, int>>( SCMinMaxLoc<Real, int> * values, int nb_values, const SynchronizerOperation & op); #if AKANTU_INTEGER_SIZE > 4 AKANTU_MPI_COMM_INSTANTIATE(int); #endif -__END_AKANTU__ +} // akantu diff --git a/src/synchronizer/static_communicator_mpi.hh b/src/synchronizer/static_communicator_mpi.hh index 2e909abb3..b9df5f0c9 100644 --- a/src/synchronizer/static_communicator_mpi.hh +++ b/src/synchronizer/static_communicator_mpi.hh @@ -1,131 +1,131 @@ /** * @file static_communicator_mpi.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sun Sep 05 2010 * @date last modification: Tue Jan 19 2016 * * @brief class handling parallel communication trough MPI * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_STATIC_COMMUNICATOR_MPI_HH__ #define __AKANTU_STATIC_COMMUNICATOR_MPI_HH__ /* -------------------------------------------------------------------------- */ #include "real_static_communicator.hh" /* -------------------------------------------------------------------------- */ #include <vector> -__BEGIN_AKANTU__ +namespace akantu { class MPITypeWrapper; /* -------------------------------------------------------------------------- */ class StaticCommunicatorMPI : public RealStaticCommunicator { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: StaticCommunicatorMPI(int & argc, char **& argv); virtual ~StaticCommunicatorMPI(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: template <typename T> void send(T * buffer, Int size, Int receiver, Int tag); template <typename T> void receive(T * buffer, Int size, Int sender, Int tag); template <typename T> CommunicationRequest asyncSend(T * buffer, Int size, Int receiver, Int tag); template <typename T> CommunicationRequest asyncReceive(T * buffer, Int size, Int sender, Int tag); template <typename T> void probe(Int sender, Int tag, CommunicationStatus & status); template <typename T> void allGather(T * values, int nb_values); template <typename T> void allGatherV(T * values, int * nb_values); template <typename T> void gather(T * values, int nb_values, int root); template <typename T> void gather(T * values, int nb_values, T * gathered, int nb_gathered = 0); template <typename T> void gatherV(T * values, int * nb_values, int root); template <typename T> void broadcast(T * values, int nb_values, int root); bool testRequest(CommunicationRequest & request); void wait(CommunicationRequest & request); void waitAll(std::vector<CommunicationRequest> & requests); UInt waitAny(std::vector<CommunicationRequest> & requests); void barrier(); template <typename T> void reduce(T * values, int nb_values, const SynchronizerOperation & op, int root); template <typename T> void allReduce(T * values, int nb_values, const SynchronizerOperation & op); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: const MPITypeWrapper & getMPITypeWrapper() const { return *mpi_data; } MPITypeWrapper & getMPITypeWrapper() { return *mpi_data; } int getMinTag(); int getMaxTag(); private: void setRank(int prank) { this->prank = prank; } void setSize(int psize) { this->psize = psize; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: friend class MPITypeWrapper; MPITypeWrapper * mpi_data; bool is_externaly_initialized; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "static_communicator_mpi_inline_impl.hh" -__END_AKANTU__ +} // akantu #endif /* __AKANTU_STATIC_COMMUNICATOR_MPI_HH__ */ diff --git a/src/synchronizer/synchronizer_registry.cc b/src/synchronizer/synchronizer_registry.cc index 11f1fc4e1..0c8ce1398 100644 --- a/src/synchronizer/synchronizer_registry.cc +++ b/src/synchronizer/synchronizer_registry.cc @@ -1,139 +1,139 @@ /** * @file synchronizer_registry.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Jun 16 2011 * @date last modification: Thu Oct 08 2015 * * @brief Registry of synchronizers * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "synchronizer_registry.hh" #include "synchronizer.hh" /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ +namespace akantu { /* -------------------------------------------------------------------------- */ SynchronizerRegistry::SynchronizerRegistry() : data_accessor(nullptr) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SynchronizerRegistry::~SynchronizerRegistry() { AKANTU_DEBUG_IN(); synchronizers.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SynchronizerRegistry::registerDataAccessor( DataAccessorBase & data_accessor) { this->data_accessor = &data_accessor; } /* -------------------------------------------------------------------------- */ void SynchronizerRegistry::synchronize(SynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(data_accessor != NULL, "No data accessor set."); std::pair<Tag2Sync::iterator, Tag2Sync::iterator> range = synchronizers.equal_range(tag); for (Tag2Sync::iterator it = range.first; it != range.second; ++it) { it->second->synchronize(*data_accessor, tag); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SynchronizerRegistry::asynchronousSynchronize(SynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(data_accessor != NULL, "No data accessor set."); std::pair<Tag2Sync::iterator, Tag2Sync::iterator> range = synchronizers.equal_range(tag); for (Tag2Sync::iterator it = range.first; it != range.second; ++it) { (*it).second->asynchronousSynchronize(*data_accessor, tag); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SynchronizerRegistry::waitEndSynchronize(SynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(data_accessor != NULL, "No data accessor set."); std::pair<Tag2Sync::iterator, Tag2Sync::iterator> range = synchronizers.equal_range(tag); for (Tag2Sync::iterator it = range.first; it != range.second; ++it) { (*it).second->waitEndSynchronize(*data_accessor, tag); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SynchronizerRegistry::registerSynchronizer(Synchronizer & synchronizer, SynchronizationTag tag) { AKANTU_DEBUG_IN(); synchronizers.insert( std::pair<SynchronizationTag, Synchronizer *>(tag, &synchronizer)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SynchronizerRegistry::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "SynchronizerRegistry [" << std::endl; Tag2Sync::const_iterator it; for (it = synchronizers.begin(); it != synchronizers.end(); it++) { stream << space << " + Synchronizers for tag " << (*it).first << " [" << std::endl; (*it).second->printself(stream, indent + 1); stream << space << " ]" << std::endl; } stream << space << "]" << std::endl; } -__END_AKANTU__ +} // akantu