diff --git a/cmake/AkantuConfig.cmake.in b/cmake/AkantuConfig.cmake.in index 2cd620eb2..85b95cc67 100644 --- a/cmake/AkantuConfig.cmake.in +++ b/cmake/AkantuConfig.cmake.in @@ -1,63 +1,63 @@ #=============================================================================== # @file AkantuConfig.cmake.in # # @author Nicolas Richart # # @date Thu Dec 01 18:00:05 2011 # # @brief CMake file for the library # # @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 . # #=============================================================================== # Compute paths get_filename_component(AKANTU_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) set(AKANTU_USE_FILE "${AKANTU_CMAKE_DIR}/AkantuUse.cmake") include(${AKANTU_USE_FILE}) if(EXISTS "${AKANTU_CMAKE_DIR}/CMakeCache.txt") # In build tree include("${AKANTU_CMAKE_DIR}/AkantuBuildTreeSettings.cmake") else() set(AKANTU_INCLUDE_DIR "${AKANTU_CMAKE_DIR}/../../include/akantu") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${AKANTU_CMAKE_DIR}/cmake") endif() include("${AKANTU_CMAKE_DIR}/AkantuLibraryDepends.cmake") -# Dependancies +# Dependencies include("${AKANTU_CMAKE_DIR}/AkantuConfigInclude.cmake") -# foreach(_extra_opt ${AKANTU_OPTION_LIST}) -# list(APPEND AKANTU_EXTRA_LIBRARIES ${AKANTU_${_extra_opt}_LIBRARIES}) -# list(APPEND AKANTU_EXTRA_INCLUDE_DIR ${AKANTU_${_extra_opt}_INCLUDE_DIR}) -# endforeach() set(AKANTU_BUILD_TYPE @CMAKE_BUILD_TYPE@) # find_akantu_dependencies() - set(AKANTU_LIBRARY akantu) if(AKANTU_HAS_CORE_CXX11) add_definitions(-std=c++0x) endif() list(APPEND AKANTU_LIBRARIES ${AKANTU_LIBRARY} ${AKANTU_EXTRA_LIBRARIES}) list(APPEND AKANTU_INCLUDE_DIR ${AKANTU_EXTRA_INCLUDE_DIR}) + +# set(AKANTU_VERSION @AKANTU_VERSION@) +# @PACKAGE_INIT@ +# set_and_check(AKANTU_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") +# check_required_components(Akantu) \ No newline at end of file diff --git a/cmake/AkantuInstall.cmake b/cmake/AkantuInstall.cmake index 52ca121e7..24d1e5789 100644 --- a/cmake/AkantuInstall.cmake +++ b/cmake/AkantuInstall.cmake @@ -1,130 +1,142 @@ #=============================================================================== # @file AkantuInstall.cmake # # @author Nicolas Richart # # @date Wed Oct 17 15:19:18 2012 # # @brief Create the files that allows users to link with Akantu in an other # cmake project # # @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 . # #=============================================================================== #=============================================================================== # Config gen for external packages #=============================================================================== configure_file(cmake/AkantuBuildTreeSettings.cmake.in "${PROJECT_BINARY_DIR}/AkantuBuildTreeSettings.cmake" @ONLY) file(WRITE "${PROJECT_BINARY_DIR}/AkantuConfigInclude.cmake" " #=============================================================================== # @file AkantuConfigInclude.cmake # @author Nicolas Richart # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # # Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== ") foreach(_option ${AKANTU_PACKAGE_SYSTEM_PACKAGES_NAMES_LIST_ALL}) list(FIND AKANTU_OPTION_LIST ${_option_name} _index) if (_index EQUAL -1) if(NOT "${_option}" STREQUAL "CORE") if(NOT AKANTU_${_option}) set(AKANTU_${_option} OFF) endif() file(APPEND "${PROJECT_BINARY_DIR}/AkantuConfigInclude.cmake" " set(AKANTU_HAS_${_option} ${AKANTU_${_option}})") endif() endif() endforeach() file(APPEND "${PROJECT_BINARY_DIR}/AkantuConfigInclude.cmake" " set(AKANTU_HAS_PARTITIONER ${AKANTU_PARTITIONER}) set(AKANTU_HAS_SOLVER ${AKANTU_SOLVER}) ") foreach(_option ${AKANTU_OPTION_LIST}) package_pkg_name(${_option} _pkg_name) file(APPEND "${PROJECT_BINARY_DIR}/AkantuConfigInclude.cmake" " list(APPEND AKANTU_OPTION_LIST ${_option}) set(AKANTU_USE_${_option} ${AKANTU_${_option}})") if(${_pkg_name}_LIBRARIES) file(APPEND "${PROJECT_BINARY_DIR}/AkantuConfigInclude.cmake" " set(${_pkg_name}_LIBRARIES ${${_pkg_name}_LIBRARIES})") endif() if(${_pkg_name}_INCLUDE_DIR) file(APPEND "${PROJECT_BINARY_DIR}/AkantuConfigInclude.cmake" " set(${_pkg_name}_INCLUDE_DIR ${${_pkg_name}_INCLUDE_DIR}) ") endif() endforeach() file(APPEND "${PROJECT_BINARY_DIR}/AkantuConfigInclude.cmake" " set(AKANTU_BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS}) set(AKANTU_BOOST_LIBRARIES ${Boost_LIBRARIES}) ") # Create the AkantuConfig.cmake and AkantuConfigVersion files get_filename_component(CONF_REL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}" ABSOLUTE) configure_file(cmake/AkantuConfig.cmake.in "${PROJECT_BINARY_DIR}/AkantuConfig.cmake" @ONLY) configure_file(cmake/AkantuConfigVersion.cmake.in "${PROJECT_BINARY_DIR}/AkantuConfigVersion.cmake" @ONLY) configure_file(cmake/AkantuUse.cmake "${PROJECT_BINARY_DIR}/AkantuUse.cmake" COPYONLY) + +# include(CMakePackageConfigHelpers) + +# configure_package_config_file(cmake/AkantuConfig.cmake.in ${PROJECT_BINARY_DIR}/AkantuConfig.cmake +# INSTALL_DESTINATION "${CONF_REL_INCLUDE_DIR}lib/akantu/cmake" +# PATH_VARS "${CONF_REL_INCLUDE_DIR}/include" ) + +# write_basic_package_version_file(${PROJECT_BINARY_DIR}/AkantuConfigVersion.cmake +# VERSION "${AKANTU_VERSION}" +# COMPATIBILITY SameMajorVersion) + + # Install the export set for use with the install-tree install(FILES ${PROJECT_BINARY_DIR}/AkantuConfig.cmake ${PROJECT_BINARY_DIR}/AkantuConfigInclude.cmake ${PROJECT_BINARY_DIR}/AkantuConfigVersion.cmake ${PROJECT_SOURCE_DIR}/cmake/AkantuUse.cmake DESTINATION lib/akantu COMPONENT dev) install(FILES ${PROJECT_SOURCE_DIR}/cmake/Modules/FindIOHelper.cmake ${PROJECT_SOURCE_DIR}/cmake/Modules/FindQVIEW.cmake ${PROJECT_SOURCE_DIR}/cmake/Modules/FindMumps.cmake ${PROJECT_SOURCE_DIR}/cmake/Modules/FindScotch.cmake ${PROJECT_SOURCE_DIR}/cmake/Modules/FindGMSH.cmake DESTINATION lib/akantu/cmake COMPONENT dev) diff --git a/doc/manual/manual-appendix-materials.tex b/doc/manual/manual-appendix-materials.tex index f27c11633..d08383490 100644 --- a/doc/manual/manual-appendix-materials.tex +++ b/doc/manual/manual-appendix-materials.tex @@ -1,80 +1,110 @@ \chapter{Material parameters} \label{app:material-parameters} \section{Linear elastic isotropic} -\begin{MaterialDesc}{elastic}{ssect:smm:linear-elastic} +\begin{MaterialDesc}{elastic}{ssect:smm:linear-elastic-isotropic} \matparam{rho}{Real}{Density} \matparam{E}{Real}{Young's modulus} \matparam{nu}{Real}{Poisson's ratio} \matparam{Plane\_Stress}{bool}{Plane stress simplification (only 2D problems)} \end{MaterialDesc} +\section{Linear elastic anisotropic} +\begin{MaterialDesc}{elastic\_anisotropic}{ssect:smm:linear-elastic-anisotropic} +\matparam{rho}{Real}{Density} +\matparam{n1}{Vector}{Direction of the main material axis} +\matparam{n2}{Vector}{Direction of the second material axis (if + applicable)} +\matparam{n3}{Vector}{Direction of the third material axis (if + applicable)} +\matparam{C..}{Real}{Coefficient ij of the material tensor C (all the 36 values + in Voigt notation can be entered .)} +\end{MaterialDesc} + +\section{Linear elastic orthotropic} +\begin{MaterialDesc}{elastic\_orthotropic}{ssect:smm:linear-elastic-orthotropic} +\matparam{rho}{Real}{Density} +\matparam{n1}{Vector}{Direction of the main material axis} +\matparam{n2}{Vector}{Direction of the second material axis (if + applicable)} +\matparam{n3}{Vector}{Direction of the third material axis (if + applicable)} +\matparam{E1 }{Real}{Young's modulus (n1)} +\matparam{E2 }{Real}{Young's modulus (n2)} +\matparam{E3 }{Real}{Young's modulus (n3)} +\matparam{nu12}{Real}{Poisson's ratio (12)} +\matparam{nu13}{Real}{Poisson's ratio (13)} +\matparam{nu23}{Real}{Poisson's ratio (23)} +\matparam{G12 }{Real}{Shear modulus (12)} +\matparam{G13 }{Real}{Shear modulus (13)} +\matparam{G23 }{Real}{Shear modulus (23)} +\end{MaterialDesc} + \section{Neohookean (finite strains)} \begin{MaterialDesc}{neohookean}{ssect:smm:cl:neohookean} \matparam{rho}{Real}{Density} \matparam{E}{Real}{Young's modulus} \matparam{nu}{Real}{Poisson's ratio} \matparam{Plane\_Stress}{bool}{Plane stress simplification (only 2D problems)} \end{MaterialDesc} \section{Standard linear solid} \begin{MaterialDesc}{sls\_deviatoric}{ssect:smm:cl:sls} \matparam{rho}{Real}{Density} \matparam{E}{Real}{Young's modulus} \matparam{nu}{Real}{Poisson's ratio} \matparam{Plane\_Stress}{bool}{Plane stress simplification (only 2D problems)} \matparam{Eta}{Real}{Viscosity} \matparam{Ev}{Real}{Stiffness of the viscous element} \end{MaterialDesc} \section{Elasto-plastic linear isotropic hardening} \begin{MaterialDesc}{plastic\_linear\_isotropic\_hardening}{ssect:smm:cl:plastic} \matparam{rho}{Real}{Density} \matparam{E}{Real}{Young's modulus} \matparam{nu}{Real}{Poisson's ratio} -\matparam{Plane\_Stress}{bool}{Plane stress simplification (only 2D problems)} \matparam{h}{Real}{Hardening modulus} \matparam{sigma\_y}{Real}{Yielding stress} \end{MaterialDesc} \section{Damage: Marigo} \begin{MaterialDesc}{marigo}{ssect:smm:cl:damage-marigo} \matparam{rho}{Real}{Density} \matparam{E}{Real}{Young's modulus} \matparam{nu}{Real}{Poisson's ratio} \matparam{Plane\_Stress}{bool}{Plane stress simplification (only 2D problems)} \matparam{Yd}{Random}{Rupture criterion} \matparam{S}{Real}{Damage Energy} \end{MaterialDesc} \section{Damage: Mazars} \begin{MaterialDesc}{mazars}{ssect:smm:cl:damage-mazars} \matparam{rho}{Real}{Density} \matparam{E}{Real}{Young's modulus} \matparam{nu}{Real}{Poisson's ratio} \matparam{At}{Real}{Traction post-peak asymptotic value} \matparam{Bt}{Real}{Traction decay shape} \matparam{Ac}{Real}{Compression post-peak asymptotic value} \matparam{Bc}{Real}{Compression decay shape} \matparam{K0}{Real}{Damage threshold} \matparam{beta}{Real}{Shear parameter} \end{MaterialDesc} \IfFileExists{manual-appendix-materials-extra-materials.tex}{\input{manual-appendix-materials-extra-materials}}{} \IfFileExists{manual-appendix-materials-cohesive.tex}{\input{manual-appendix-materials-cohesive}}{} %%% Local Variables: %%% mode: latex %%% TeX-master: "manual" %%% End: diff --git a/doc/manual/manual-cohesive_laws.tex b/doc/manual/manual-cohesive_laws.tex index fbf8c6253..4185d9645 100644 --- a/doc/manual/manual-cohesive_laws.tex +++ b/doc/manual/manual-cohesive_laws.tex @@ -1,151 +1,150 @@ \subsection{Cohesive laws} \label{sec:cohesive-laws} -\subsubsection{Snozzi-Molinari Law}\label{ssect:smm:cl:coh-snozzi} +\subsubsection{Snozzi-Molinari Law\matlabel{ssect:smm:cl:coh-snozzi}} \begin{figure}[!hbt] \centering \subfloat[Linear]{\includegraphics[width=0.4\textwidth]{figures/linear_cohesive_law}} \qquad \subfloat[Bilinear]{\includegraphics[width=0.4\textwidth]{figures/bilinear_cohesive_law}} \caption{Irreversible cohesive laws for explicit simulations.} \label{fig:smm:coh:linear_cohesive_law} \end{figure} \akantu includes the Snozzi-Molinari~\cite{snozzi_cohesive_2013} linear irreversible cohesive law (see Figure~\ref{fig:smm:coh:linear_cohesive_law}). It is an extension to the Camacho-Ortiz~\cite{camacho_computational_1996} cohesive law in order to make dissipated fracture energy path-dependent. The concept of free potential energy is dropped and a new independent parameter $\kappa$ is introduced: \begin{equation} \kappa = \frac{G_\mathrm{c, II}}{G_\mathrm{c, I}} \end{equation} where $G_\mathrm{c, I}$ and $G_\mathrm{c, II}$ are the necessary works of separation per unit area to open completely a cohesive zone under mode I and mode II, respectively. Their model yields to the following equation for cohesive tractions $\vec{T}$ in case of crack opening ${\delta}$: \begin{equation} \label{eq:smm:coh:tractions} \vec{T} = \left( \frac{\beta^2}{\kappa} \Delta_\mathrm{t} \vec{t} + \Delta_\mathrm{n} \vec{n} \right) \frac{\sigma_\mathrm{c}}{\delta} \left( 1- \frac{\delta}{\delta_\mathrm{c}} \right) = \hat{\vec T}\, \frac{\sigma_\mathrm{c}}{\delta} \left( 1- \frac{\delta}{\delta_\mathrm{c}} \right) \end{equation} where $\sigma_\mathrm{c}$ is the material strength along the fracture, $\delta_\mathrm{c}$ the critical effective displacement after which cohesive tractions are zero (complete decohesion), $\Delta_\mathrm{t}$ and $\Delta_\mathrm{n}$ are the tangential and normal components of the opening displacement vector $\vec{\Delta}$, respectively. The parameter $\beta$ is a weight that indicates how big the tangential opening contribution is. The effective opening displacement is: \begin{equation} \delta = \sqrt{\frac{\beta^2}{\kappa^2} \Delta_\mathrm{t}^2 + \Delta_\mathrm{n}^2} \end{equation} In case of unloading or reloading $\delta < \delta_\mathrm{max}$, tractions are calculated as: \begin{align} T_\mathrm{n} &= \Delta_\mathrm{n}\, \frac{\sigma_\mathrm{c}}{\delta_\mathrm{max}} \left( 1- \frac{\delta_\mathrm{max}}{\delta_\mathrm{c}} \right) \\ T_\mathrm{t} &= \frac{\beta^2}{\kappa}\, \Delta_\mathrm{t}\, \frac{\sigma_\mathrm{c}}{\delta_\mathrm{max}} \left( 1- \frac{\delta_\mathrm{max}}{\delta_\mathrm{c}} \right) \end{align} so that they vary linearly between the origin and the maximum attained tractions. As shown in Figure~\ref{fig:smm:coh:linear_cohesive_law}, in this law, the dissipated and reversible energies are: \begin{align} E_\mathrm{diss} &= \frac{1}{2} \sigma_\mathrm{c}\, \delta_\mathrm{max}\\[1ex] E_\mathrm{rev} &= \frac{1}{2} T\, \delta \end{align} Moreover, a damage parameter $D$ can be defined as: \begin{equation} D = \min \left( \frac{\delta_\mathrm{max}}{\delta_\mathrm{c}},1 \right) \end{equation} which varies from 0 (undamaged condition) and 1 (fully damaged condition). This variable can only increase because damage is an irreversible process. A simple penalty contact model has been incorporated in the cohesive law so that normal tractions can be returned in case of compression: \begin{equation} T_\mathrm{n} = \alpha \Delta_\mathrm{n} \quad\text{if $\Delta_\mathrm{n} < 0$} \end{equation} where $\alpha$ is a stiffness parameter that defaults to zero. The relative contact energy is equivalent to reversible energy but in compression. The material name of the linear decreasing cohesive law is \code{material\_cohesive\_linear} and its parameters with their respective default values are: \begin{itemize} \item \code{sigma\_c}: 0 \item \code{beta}: 0 \item \code{G\_cI}: 0 \item \code{G\_cII}: 0 \item \code{kappa}: 1 \item \code{penalty}: 0 \end{itemize} A random number generator can be used to assign a random $\sigma_\mathrm{c}$ to each facet following a given distribution (see Section~\ref{sect:smm:CL}). The bilinear constitutive law works exactly the same way as the linear one, except for the additional parameter \code{delta\_0} that by default is zero. Two examples for the extrinsic and intrinsic cohesive elements and also an example to assign different properties to intergranular and transgranular cohesive elements can be found in the folder \code{\examplesdir/cohesive\_element/}. -\subsubsection{Exponential Cohesive Law} -\label{ssect:smm:cl:coh-exponential} +\subsubsection{Exponential Cohesive Law\matlabel{ssect:smm:cl:coh-exponential}} Ortiz and Pandolfi proposed this cohesive law in 1999~\cite{ortiz1999}. The traction-opening equation for this law is as follows: \begin{equation} \label{eq:exponential_law} T = e \sigma_c \frac{\delta}{\delta_c}e^{-\delta/ \delta_c} \end{equation} This equation is plotted in Figure~\ref{fig:smm:CL:ECL}. The term $\partial{\vec{T}}/ \partial{\delta}$ of equation~\eqref{eq:cohesive_stiffness} after the necessary derivation can expressed as \begin{equation} \label{eq:tangent_cohesive} \frac{\partial{\vec{T}}} {\partial{\delta}} = \hat{\vec{T}} \otimes \frac {\partial{(T/\delta)}}{\partial{\delta}} \frac{\hat{\vec{T}}}{\delta}+ \frac{T}{\delta} \left[ \beta^2 \mat{I} + \left(1-\beta^2\right) \left(\vec{n} \otimes \vec{n}\right)\right] \end{equation} where \begin{equation} \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. \end{equation} \begin{figure}[!htb] \begin{center} \includegraphics[width=0.6\textwidth,keepaspectratio=true]{figures/cohesive_exponential.pdf} \caption{Exponential cohesive law} \label{fig:smm:CL:ECL} \end{center} \end{figure} %%% Local Variables: %%% mode: latex %%% TeX-master: "manual" %%% End: diff --git a/doc/manual/manual-constitutive-laws.tex b/doc/manual/manual-constitutive-laws.tex index 8a8661a8a..23a8f9eb6 100644 --- a/doc/manual/manual-constitutive-laws.tex +++ b/doc/manual/manual-constitutive-laws.tex @@ -1,380 +1,529 @@ \section{Constitutive Laws \label{sect:smm:CL}}\index{Material} In order to compute an element's response to deformation, one needs to use an appropriate constitutive relationship. The constitutive law is used to compute the element's stresses from the element's strains. In the finite-element discretization, the constitutive formulation is applied to every quadrature point of each element. When the implicit formulation is used, the tangent matrix has to be computed. The chosen materials for the simulation have to be specified in the mesh file or, as an alternative, they can be assigned using the \code{element\_material} vector. For every material assigned to the problem one has to specify the material characteristics (constitutive behavior and material properties) in a text file (\eg material.dat) as follows: \begin{cpp} material %\emph{constitutive\_law}% %\emph{}% [ name = $value$ rho = $value$ ... ] \end{cpp} \index{Constitutive\_laws} where \emph{constitutive\_law} is the adopted constitutive law, followed by the material properties listed one by line in the bracket (\eg \code{name} and density \code{rho}). Some constitutive laws can also have an \emph{optional flavor}. For example a non-local constitutive law can be flavored by a weight function. The file needs to be loaded in \akantu using the \code{initialize} method of \akantu (as shown in Section~\ref{sec:writing_main}) \begin{cpp} initialize("material.dat", argc, argv); \end{cpp} % or, alternatively, the \code{initFull} method. % \begin{cpp} % model.initFull("material.dat"); % \end{cpp} In order to conveniently store values at each quadrature in a material point \akantu provides a special data structure, the \code{InternalField}. The internal fields are inheriting from the \code{ElementTypeMapArray}. Furthermore, it provides several functions for initialization, auto-resizing and auto removal of quadrature points. Sometimes it is also desired to generate random distributions of internal parameters. An example might be the critical stress at which the material fails. To generate such a field, in the material input file, a random quantity needs be added to the base value: \begin{cpp} sigma_c = $base$ sigma_c = $base$ uniform [$min$, $max$] sigma_c = $base$ weibull [$\lambda$, $m$] \end{cpp} All parameters are real numbers. For the uniform distribution, minimum and maximum values have to be specified. Random parameters are defined as a $base$ value to which we add a random number that follows the chosen distribution. The \href{http://en.wikipedia.org/wiki/Uniform\_distribution\_(continuous)}{\emph{Uniform}} distribution is gives a random values between in $[min, max)$ The \href{http://en.wikipedia.org/wiki/Weibull\_distribution}{\emph{Weibull}} distribution is characterized by the following cumulative distribution function: \begin{equation} F(x) = 1- e^{-\left({x/\lambda}\right)^m} \end{equation} which depends on $m$ and $\lambda$, which are the shape parameter and the scale parameter. The following sections describe the constitutive models implemented in \akantu. In Appendix~\ref{app:material-parameters} a summary of the parameters for all materials of \akantu is provided. -\subsection{Elasticity\label{ssect:smm:linear-elastic}}\index{Material!Elastic} -The elastic law is a commonly used constitutive relationship that can -be used for a wide range of engineering materials (\eg metals, -concrete, rock, wood, glass, rubber, etc.) provided that the strains -remain small (\ie small deformation and stress lower than yield -strength). The linear elastic behavior is described by Hooke's law, -which states that the stress is linearly proportional to the applied -strain (material behaves like an ideal spring), as illustrated in -Figure~\ref{fig:smm:cl:elastic}. +\subsection{Elasticity}\index{Material!Elastic} + +The elastic law is a commonly used constitutive relationship that can be used +for a wide range of engineering materials (\eg metals, concrete, rock, wood, +glass, rubber, etc.) provided that the strains remain small (\ie small +deformation and stress lower than yield strength). + +The elastic laws are often expressed as $\mat{\sigma} = +\mat{C}:\mat{\varepsilon}$ with where $\mat{\sigma}$ is the Cauchy stress tensor, +$\mat{\varepsilon}$ represents the infinitesimal strain tensor and $\mat{C}$ is the +elastic modulus tensor. + +\subsubsection{Linear isotropic\matlabel{ssect:smm:linear-elastic-isotropic}} + +The linear isotropic elastic behavior is described by Hooke's law, which states +that the stress is linearly proportional to the applied strain (material behaves +like an ideal spring), as illustrated in Figure~\ref{fig:smm:cl:elastic}. \begin{figure}[!htb] \begin{center} \subfloat[]{ - \includegraphics[width=0.4\textwidth,keepaspectratio=true]{figures/stress_strain_el.pdf} + \begin{tikzpicture} + \draw[thick,latex-latex] (0,5) node[left] {$\sigma$} |- (5,0) node (x) [right, below] {$\varepsilon$}; + \draw[thin] (1.5,1.5) -- (2.5,1.5) -- (2.5,2.5) node [midway, right] {E}; + \draw[very thick,color=red] (0,0) -- (4,4); + \draw[very thick,latex-latex,color=red] (1,1) -- (3,3); + \end{tikzpicture} \label{fig:smm:cl:elastic:stress_strain} } \hspace{0.05\textwidth} \subfloat[]{ \raisebox{0.125\textwidth}{\includegraphics[width=0.25\textwidth,keepaspectratio=true]{figures/hooke_law.pdf}} \label{fig:smm:cl:elastic:hooke} } \caption{(a) Stress-strain curve for elastic material and (b) schematic representation of Hooke's law, denoted as a spring.} \label{fig:smm:cl:elastic} \end{center} \end{figure} The equation that relates the strains to the displacements is: % First the strain is computed (at every gauss point) from the displacements as follows: \begin{equation} \label{eqn:smm:strain_inf} - \mat{\epsilon} = - \frac{1}{2} \left[ \mat{F}-\mat{I}+(\mat{F}-\mat{I})^T \right] + \mat{\varepsilon} = + \frac{1}{2} \left[ \nabla_0 \vec{u}+\nabla_0 \vec{u}^T \right] \end{equation} -where $\mat{\epsilon}$ represents the infinitesimal strain tensor, -$\mat{F} = \nabla_{\!\!\vec{X}}\vec{x}$ the deformation gradient -tensor and $\mat{I}$ the identity matrix. The constitutive equation +where $\mat{\varepsilon}$ represents the infinitesimal strain tensor, +$\nabla_{0}\vec{u}$ the displacement gradient +tensor according to the initial configuration. The constitutive equation for isotropic homogeneous media can be expressed as: \begin{equation} \label{eqn:smm:material:constitutive_elastic} - \mat{\sigma } =\lambda\mathrm{tr}(\mat{\epsilon})\mat{I}+2 \mu\mat{\epsilon} + \mat{\sigma } =\lambda\mathrm{tr}(\mat{\varepsilon})\mat{I}+2 \mu\mat{\varepsilon} \end{equation} where $\mat{\sigma}$ is the Cauchy stress tensor ($\lambda$ and $\mu$ are the the first and second Lame's -coefficients). Besides the name and density, one has to specify the -following properties in the material file: \code{E} (Young's modulus), -\code{nu} (Poisson's ratio) and (for 2D) \code{Plane\_Stress} (if set -to zero or not specified plane strain conditions are assumed for a -plain analysis, otherwise plane stress conditions are applied). +coefficients). + +In Voigt notation this correspond to +\begin{align} + \left[\begin{array}{c} + \sigma_{11}\\ + \sigma_{22}\\ + \sigma_{33}\\ + \sigma_{23}\\ + \sigma_{13}\\ + \sigma_{12}\\ + \end{array}\right] + &= \frac{E}{(1+\nu)(1-2\nu)}\left[ + \begin{array}{cccccc} + 1-\nu & \nu & \nu & 0 & 0 & 0\\ + \nu & 1-\nu & \nu & 0 & 0 & 0\\ + \nu & \nu & 1-\nu & 0 & 0 & 0\\ + 0 & 0 & 0 & \frac{1-2\nu}{2} & 0 & 0 \\ + 0 & 0 & 0 & 0 & \frac{1-2\nu}{2} & 0 \\ + 0 & 0 & 0 & 0 & 0 & \frac{1-2\nu}{2} \\ + \end{array}\right] + \left[\begin{array}{c} + \varepsilon_{11}\\ + \varepsilon_{22}\\ + \varepsilon_{33}\\ + 2\varepsilon_{23}\\ + 2\varepsilon_{13}\\ + 2\varepsilon_{12}\\ + \end{array}\right] +\end{align} + +\subsubsection{Linear anisotropic\matlabel{ssect:smm:linear-elastic-anisotropic}} +This formulation is not sufficient to represent all elastic material +behavior. Some materials have characteristic orientation that have to be taken +into account. To represent this anisotropy a more general stress-strain law has +to be used. For this we define the elastic modulus tensor as follow: + +\begin{align} + \left[\begin{array}{c} + \sigma_{11}\\ + \sigma_{22}\\ + \sigma_{33}\\ + \sigma_{23}\\ + \sigma_{13}\\ + \sigma_{12}\\ + \end{array}\right] + &= \left[ + \begin{array}{cccccc} + c_{11} & c_{12} & c_{13} & c_{14} & c_{15} & c_{16}\\ + c_{21} & c_{22} & c_{23} & c_{24} & c_{25} & c_{26}\\ + c_{31} & c_{32} & c_{33} & c_{34} & c_{35} & c_{36}\\ + c_{41} & c_{42} & c_{43} & c_{44} & c_{45} & c_{46}\\ + c_{51} & c_{52} & c_{53} & c_{54} & c_{55} & c_{56}\\ + c_{61} & c_{62} & c_{63} & c_{64} & c_{65} & c_{66}\\ + \end{array}\right] + \left[\begin{array}{c} + \varepsilon_{11}\\ + \varepsilon_{22}\\ + \varepsilon_{33}\\ + 2\varepsilon_{23}\\ + 2\varepsilon_{13}\\ + 2\varepsilon_{12}\\ + \end{array}\right] +\end{align} + +\begin{figure}[h] + \centering + \begin{tikzpicture} + \draw[thick,latex-latex] (90:3) node[left] {$\vec{e_2}$} |- (0:3) node [right, below] {$\vec{e_1}$}; + \draw[ultra thick,latex-latex] (150:3) node[left] {$\vec{n_2}$} -- (0,0) -- (20:3) node [right] {$\vec{n_1}$}; + \end{tikzpicture} + \caption{Material basis} +\end{figure} + +To simplify the writing of input files the \mat{C} tensor is expressed in the +material basis. And this basis as to be given too. This basis $\Omega_{\st{mat}} += \{\vec{n_1}, \vec{n_2}, \vec{n_3}\}$ is used to define the rotation $R_{ij} = +\vec{n_j} . \vec{e_i}$. And $\mat{C}$ can be rotated in the global basis $\Omega += \{\vec{e_1}, \vec{e_2}, \vec{e_3}\}$ as follow: -\subsection{Neo-Hookean\label{ssect:smm:cl:neohookean}}\index{Material!Neohookean} +\begin{align} +\mat{C}_{\Omega} &= \mat{R}_1 \mat{C}_{\Omega_{\st{mat}}} \mat{R}_2\\ +\mat{R}_1 &= \left[ + \begin{array}{cccccc} + R_{11} R_{11} & R_{12} R_{12} & R_{13} R_{13} & R_{12} R_{13} & R_{11} R_{13} & R_{11} R_{12}\\ + R_{21} R_{21} & R_{22} R_{22} & R_{23} R_{23} & R_{22} R_{23} & R_{21} R_{23} & R_{21} R_{22}\\ + R_{31} R_{31} & R_{32} R_{32} & R_{33} R_{33} & R_{32} R_{33} & R_{31} R_{33} & R_{31} R_{32}\\ + R_{21} R_{31} & R_{22} R_{32} & R_{23} R_{33} & R_{22} R_{33} & R_{21} R_{33} & R_{21} R_{32}\\ + R_{11} R_{31} & R_{12} R_{32} & R_{13} R_{33} & R_{12} R_{33} & R_{11} R_{33} & R_{11} R_{32}\\ + R_{11} R_{21} & R_{12} R_{22} & R_{13} R_{23} & R_{12} R_{23} & R_{11} R_{23} & R_{11} R_{22}\\ + \end{array}\right]\\ +\mat{R}_2 &= \left[ + \begin{array}{cccccc} + R_{11} R_{11} & R_{21} R_{21} & R_{31} R_{31} & R_{21} R_{31} & R_{11} R_{31} & R_{11} R_{21}\\ + R_{12} R_{12} & R_{22} R_{22} & R_{32} R_{32} & R_{22} R_{32} & R_{12} R_{32} & R_{12} R_{22}\\ + R_{13} R_{13} & R_{23} R_{23} & R_{33} R_{33} & R_{23} R_{33} & R_{13} R_{33} & R_{13} R_{23}\\ + R_{12} R_{13} & R_{22} R_{23} & R_{32} R_{33} & R_{22} R_{33} & R_{12} R_{33} & R_{12} R_{23}\\ + R_{11} R_{13} & R_{21} R_{23} & R_{31} R_{33} & R_{21} R_{33} & R_{11} R_{33} & R_{11} R_{23}\\ + R_{11} R_{12} & R_{21} R_{22} & R_{31} R_{32} & R_{21} R_{32} & R_{11} R_{32} & R_{11} R_{22}\\ + \end{array}\right]\\ +\end{align} + +\subsubsection{Linear orthotropic\matlabel{ssect:smm:linear-elastic-orthotropic}} + +A particular case of anisotropy is when the material basis is orthogonal in which case the elastic modulus tensor can be simplified and rewritten in terms of 9 independents material parameters. + +\begin{align} + \left[\begin{array}{c} + \sigma_{11}\\ + \sigma_{22}\\ + \sigma_{33}\\ + \sigma_{23}\\ + \sigma_{13}\\ + \sigma_{12}\\ + \end{array}\right] + &= \left[ + \begin{array}{cccccc} + c_{11} & c_{12} & c_{13} & 0 & 0 & 0 \\ + & c_{22} & c_{23} & 0 & 0 & 0 \\ + & & c_{33} & 0 & 0 & 0 \\ + & & & c_{44} & 0 & 0 \\ + & \multicolumn{2}{l}{\text{sym.}} & & c_{55} & 0 \\ + & & & & & c_{66}\\ + \end{array}\right] + \left[\begin{array}{c} + \varepsilon_{11}\\ + \varepsilon_{22}\\ + \varepsilon_{33}\\ + 2\varepsilon_{23}\\ + 2\varepsilon_{13}\\ + 2\varepsilon_{12}\\ + \end{array}\right] +\end{align} + +\begin{align} + c_{11} &= E_1 (1 - \nu_{23}\nu_{32})\Gamma \qquad c_{22} = E_2 (1 - \nu_{13}\nu_{31})\Gamma \qquad c_{33} = E_3 (1 - \nu_{12}\nu_{21})\Gamma\\ + c_{12} &= E_1 (\nu_{21} - \nu_{31}\nu_{23})\Gamma = E_2 (\nu_{12} - \nu_{32}\nu_{13})\Gamma\\ + c_{13} &= E_1 (\nu_{31} - \nu_{21}\nu_{32})\Gamma = E_2 (\nu_{13} - \nu_{21}\nu_{23})\Gamma\\ + c_{23} &= E_2 (\nu_{32} - \nu_{12}\nu_{31})\Gamma = E_3 (\nu_{23} - \nu_{21}\nu_{13})\Gamma\\ + c_{44} &= \mu_{23} \qquad c_{55} = \mu_{13} \qquad c_{66} = \mu_{12} \\ + \Gamma &= \frac{1}{1 - \nu_{12} \nu_{21} - \nu_{13} \nu_{31} - \nu_{32} \nu_{23} - 2 \nu_{21} \nu_{32} \nu_{13}} +\end{align} + +The poison ratios follow the rule $\nu_{ij} = \nu_{ji} E_i / E_j$. + +\subsection{Neo-Hookean\matlabel{ssect:smm:cl:neohookean}}\index{Material!Neohookean} The hyperelastic Neo-Hookean constitutive law results from an extension of the linear elastic relationship (Hooke's Law) for large deformation. Thus, the model predicts nonlinear stress-strain behavior for bodies undergoing large deformations. \begin{figure}[!htb] \begin{center} \includegraphics[width=0.4\textwidth,keepaspectratio=true]{figures/stress_strain_neo.pdf} \caption{Neo-hookean Stress-strain curve.} \label{fig:smm:cl:neo_hookean} \end{center} \end{figure} As illustrated in Figure~\ref{fig:smm:cl:neo_hookean}, the behavior is initially linear and the mechanical behavior is very close to the corresponding linear elastic material. This constitutive relationship, which accounts for compressibility, is a modified version of the one proposed by Ronald Rivlin \cite{Belytschko:2000}. The strain energy stored in the material is given by: \begin{equation}\label{eqn:smm:constitutive:neohookean_potential} \Psi(\mat{C}) = \frac{1}{2}\lambda_0\left(\ln J\right)^2-\mu_0\ln J+\frac{1}{2} \mu_0\left(\mathrm{tr}(\mat{C})-3\right) \end{equation} -\noindent where $\lambda_0$ and $\mu_0$ are, respectively, Lamé's first parameter +\noindent where $\lambda_0$ and $\mu_0$ are, respectively, Lam\'e's first parameter and the shear modulus at the initial configuration. $J$ is the jacobian of the deformation gradient ($\mat{F}=\nabla_{\!\!\vec{X}}\vec{x}$): $J=\text{det}(\mat{F})$. Finally $\mat{C}$ is the right Cauchy-Green deformation tensor. Since this kind of material is used for large deformation problems, a finite deformation framework should be used. Therefore, the Cauchy stress ($\mat{\sigma}$) should be computed through the second Piola-Kirchhoff stress tensor $\mat{S}$: \begin{equation} \mat{\sigma } = \frac{1}{J}\mat{F}\mat{S}\mat{F}^T \end{equation} Finally the second Piola-Kirchhoff stress tensor is given by: \begin{equation} \mat{S} = 2\frac{\partial\Psi}{\partial\mat{C}} = \lambda_0\ln J \mat{C}^{-1}+\mu_0\left(\mat{I}-\mat{C}^{-1}\right) \end{equation} The parameters to indicate in the material file are the same as those for the elastic case: \code{E} (Young's modulus), \code{nu} (Poisson's ratio). -\subsection{Visco-Elasticity} - -\label{ssect:smm:cl:sls} +\subsection{Visco-Elasticity\matlabel{ssect:smm:cl:sls}} % Standard Solid rheological model, see [] J.C. Simo, T.J.R. Hughes, % "Computational Inelasticity", Springer (1998), see Sections 10.2 and 10.3 Visco-elasticity is characterized by strain rate dependent behavior. Moreover, when such a material undergoes a deformation it dissipates energy. This dissipation results in a hysteresis loop in the stress-strain curve at every loading cycle (see Figure~\ref{fig:smm:cl:visco-elastic:hyst}). In principle, it can be applied to many materials, since all materials exhibit a visco-elastic behavior if subjected to particular conditions (such as high temperatures). \begin{figure}[!htb] \begin{center} \subfloat[]{ \includegraphics[width=0.4\textwidth,keepaspectratio=true]{figures/stress_strain_visco.pdf} \label{fig:smm:cl:visco-elastic:hyst} } \hspace{0.05\textwidth} \subfloat[]{ \raisebox{0.025\textwidth}{\includegraphics[width=0.3\textwidth,keepaspectratio=true]{figures/visco_elastic_law.pdf}} \label{fig:smm:cl:visco-elastic:model} } \caption{(a) Characteristic stress-strain behavior of a visco-elastic material with hysteresis loop and (b) schematic representation of the standard rheological linear solid visco-elastic model.} \label{fig:smm:cl:visco-elastic} \end{center} \end{figure} The standard rheological linear solid model (see Sections 10.2 and 10.3 of~\cite{simo92}) has been implemented in \akantu. This model results from the combination of a spring mounted in parallel with a spring and a dashpot connected in series, as illustrated in Figure~\ref{fig:smm:cl:visco-elastic:model}. The advantage of this model is that it allows to account for creep or stress relaxation. The equation that relates the stress to the strain is (in 1D): \begin{equation} - \frac{d\epsilon(t)}{dt} = \left ( E + E_V \right ) ^ {-1} \cdot \left [ \frac{d\sigma(t)}{dt} + \frac{E_V}{\eta}\sigma(t) - \frac{EE_V}{\eta}\epsilon(t) \right ] + \frac{d\varepsilon(t)}{dt} = \left ( E + E_V \right ) ^ {-1} \cdot \left [ \frac{d\sigma(t)}{dt} + \frac{E_V}{\eta}\sigma(t) - \frac{EE_V}{\eta}\varepsilon(t) \right ] \end{equation} where $\eta$ is the viscosity. The equilibrium condition is unique and is attained in the limit, as $t \to \infty $. At this stage, the response is elastic and depends on the Young's modulus $E$. The mandatory parameters for the material file are the following: \code{rho} (density), \code{E} (Young's modulus), \code{nu} (Poisson's ratio), \code{Plane\_Stress} (if set to zero plane strain, otherwise plane stress), \code{eta} (dashpot viscosity) and \code{Ev} (stiffness of the viscous element). Note that the current standard linear solid model is applied only on the deviatoric part of the strain tensor. The spheric part of the strain tensor affects the stress tensor like an linear elastic material. -\subsection{Small-Deformation Plasticity\label{ssect:smm:cl:plastic}}\index{Material!Small-deformation Plasticity} +\subsection{Small-Deformation Plasticity\matlabel{ssect:smm:cl:plastic}}\index{Material!Small-deformation Plasticity} The small-deformation plasticity is a simple plasticity material formulation which accounts for the additive decomposition of strain into elastic and plastic strain components. This formulation is applicable to infinitesimal deformation where the additive decomposition of the strain is a valid approximation. In this formulation, plastic strain is a shearing process where hydrostatic stress has no contribution to plasticity and consequently plasticity does not lead to volume change. Figure~\ref{fig:smm:cl:Lin-strain-hard} shows the linear strain hardening elasto-plastic behavior according to the additive decomposition of strain into the elastic and plastic parts in infinitesimal deformation as \begin{align} \mat{\varepsilon} &= \mat{\varepsilon}^e +\mat{\varepsilon}^p\\ {\mat{\sigma}} &= 2G(\mat{\varepsilon}^e) + \lambda \mathrm{tr}(\mat{\varepsilon}^e)\mat{I} \end{align} \begin{figure}[htp] \centering {\includegraphics[scale=0.4, clip]{figures/isotropic_hardening_plasticity.pdf}} \caption{ Stress-strain curve for the small-deformation plasticity with linear isotropic hardening. } \label{fig:smm:cl:Lin-strain-hard} \end{figure} \noindent In this class, the von Mises yield criterion is used. In the von Mises yield criterion, the yield is independent of the hydrostatic stress. Other yielding criteria such as Tresca and Gurson can be easily implemented in this class as well. In the von Mises yield criterion, the hydrostatic stresses have no effect on the plasticity and consequently the yielding occurs when a critical elastic shear energy is achieved. \begin{equation} \label{eqn:smm:constitutive:von Mises} f = \sigma_{\st{eff}} - \sigma_y = \left(\frac{3}{2} {\mat{\sigma}}^{\st{tr}} : {\mat{\sigma}}^{\st{tr}}\right)^\frac{1}{2}-\sigma_y (\mat{\varepsilon}^p) \end{equation} \begin{equation} \label{eqn:smm:constitutive:yielding} f < 0 \quad \textrm{Elastic deformation,} \qquad f = 0 \quad \textrm{Plastic deformation} \end{equation} where $\sigma_y$ is the yield strength of the material which can be function of plastic strain in case of hardening type of materials and ${\mat{\sigma}}^{\st{tr}}$ is the deviatoric part of stress given by \begin{equation} \label{eqn:smm:constitutive:deviatoric stress} {\mat{\sigma}}^{\st{tr}}=\mat{\sigma} - \frac{1}{3} \mathrm{tr}(\mat{\sigma}) \mat {I} \end{equation} After yielding $(f = 0)$, the normality hypothesis of plasticity determines the direction of plastic flow which is normal to the tangent to the yielding surface at the load point. Then, the tensorial form of the plastic constitutive equation using the von Mises yielding criterion (see equation 4.34) may be written as \begin{equation} \label{eqn:smm:constitutive:plastic contitutive equation} \Delta {\mat{\varepsilon}}^p = \Delta p \frac {\partial{f}}{\partial{\mat \sigma}}=\frac{3}{2} \Delta p \frac{{\mat{\sigma}}^{\st{tr}}}{\sigma_{\st{eff}}} \end{equation} In these expressions, the direction of the plastic strain increment (or equivalently, plastic strain rate) is given by $\frac{{\mat{\sigma}}^{\st{tr}}}{\sigma_{\st{eff}}}$ while the magnitude is defined by the plastic multiplier $\Delta p$. This can be obtained using the \emph{consistency condition} which impose the requirement for the load point to remain on the yielding surface in the plastic regime. Here, we summarize the implementation procedures for the small-deformation plasticity with linear isotropic hardening: \begin{enumerate} \item Compute the trial stress: \begin{equation} {\mat{\sigma}}^{\st{tr}} = {\mat{\sigma}}_t + 2G\Delta \mat{\varepsilon} + \lambda \mathrm{tr}(\Delta \mat{\varepsilon})\mat{I} \end{equation} \item Check the Yielding criteria: \begin{equation} f = (\frac{3}{2} {\mat{\sigma}}^{\st{tr}} : {\mat{\sigma}}^{\st{tr}})^{1/2}-\sigma_y (\mat{\varepsilon}^p) \end{equation} \item Compute the Plastic multiplier: \begin{align} d \Delta p &= \frac{\sigma^{tr}_{eff} - 3G \Delta P^{(k)}- \sigma_y^{(k)}}{3G + h}\\ \Delta p^{(k+1)} &= \Delta p^{(k)}+ d\Delta p\\ \sigma_y^{(k+1)} &= (\sigma_y)_t+ h\Delta p \end{align} \item Compute the plastic strain increment: \begin{equation} \Delta {\mat{\varepsilon}}^p = \frac{3}{2} \Delta p \frac{{\mat{\sigma}}^{\st{tr}}}{\sigma_{\st{eff}}} \end{equation} \item Compute the stress increment: \begin{equation} {\Delta \mat{\sigma}} = 2G(\Delta \mat{\varepsilon}-\Delta \mat{\varepsilon}^p) + \lambda \mathrm{tr}(\Delta \mat{\varepsilon}-\Delta \mat{\varepsilon}^p)\mat{I} \end{equation} \item Update the variables: \begin{align} {\mat{\varepsilon^p}} &= {\mat{\varepsilon}}^p_t+{\Delta {\mat{\varepsilon}}^p}\\ {\mat{\sigma}} &= {\mat{\sigma}}_t+{\Delta \mat{\sigma}} \end{align} \end{enumerate} We use an implicit integration technique called \emph{the radial return method} to obtain the plastic multiplier. This method has the advantage of being unconditionally stable, however, the accuracy remains dependent on the step size. The plastic parameters to indicate in the material file are: \code{$\sigma_y$} (Yield stress) and \code{h} (Hardening modulus). In addition, the elastic parameters need to be defined as previously mentioned: \code{E} (Young's modulus), \code{nu} (Poisson's ratio). \subsection{Damage} In the simplified case of a linear elastic and brittle material, isotropic damage can be represented by a scalar variable $d$, which varies from $0$ to $1$ for no damage to fully broken material respectively. The stress-strain relationship then becomes: \begin{equation*} \mat{\sigma} = (1-d)\, \mat{C}:\mat{\varepsilon} \end{equation*} where $\mat{\sigma}$, $\mat{\varepsilon}$ are the Cauchy stress and strain tensors, and $\mat{C}$ is the elastic stiffness tensor. This formulation relies on the definition of an evolution law for the damage variable. In \akantu, many possibilities exist and they are listed below. -\subsubsection{Marigo} -\label{ssect:smm:cl:damage-marigo} +\subsubsection{Marigo\matlabel{ssect:smm:cl:damage-marigo}} + This damage evolution law is energy based as defined by Marigo \cite{marigo81a, lemaitre96a}. It is an isotropic damage law. \begin{align} Y &= \frac{1}{2}\mat{\varepsilon}:\mat{C}:\mat{\varepsilon}\\ F &= Y - Y_d - S d\\ d &= \left\{ \begin{array}{l l} \mathrm{min}\left(\frac{Y-Y_d}{S},\;1\right) & \mathrm{if}\; F > 0\\ \mathrm{unchanged} & \mathrm{otherwise} \end{array} \right. \end{align} In this formulation, $Y$ is the strain energy release rate, $Y_d$ the rupture criterion and $S$ the damage energy. The non-local version of this damage evolution law is constructed by averaging the energy $Y$. -\subsubsection{Mazars} -\label{ssect:smm:cl:damage-mazars} +\subsubsection{Mazars\matlabel{ssect:smm:cl:damage-mazars}} This law introduced by Mazars \cite{mazars84a} is a behavioral model to represent damage evolution in concrete. The governing variable in this damage law is the equivalent strain $\varepsilon_{\st{eq}} = \sqrt{<\mat{\varepsilon}>_+:<\mat{\varepsilon}>_+}$, with $<.>_+$ the positive part of the tensor. The damage the is defined as: \begin{align} D &= \alpha_t^\beta D_t + (1-\alpha_t)^\beta D_c\\ D_t &= 1 - \frac{\kappa_0 (1- A_t)}{\varepsilon_{\st{eq}}} - A_t \exp^{-B_t(\varepsilon_{\st{eq}}-\kappa_0)}\\ D_c &= 1 - \frac{\kappa_0 (1- A_c)}{\varepsilon_{\st{eq}}} - A_c \exp^{-B_c(\varepsilon_{\st{eq}}-\kappa_0)}\\ \alpha_t &= \frac{\sum_{i=1}^3<\varepsilon_i>_+\varepsilon_{\st{nd}\;i}}{\varepsilon_{\st{eq}}^2} \end{align} With $\kappa_0$ the damage threshold, $A_t$ and $B_t$ the damage parameter in traction, $A_c$ and $B_c$ the damage parameter in compression, $\beta$ is the shear parameter. $\alpha_t$ is the coupling parameter between traction and compression, the $\varepsilon_i$ are the eigenstrain and the $\varepsilon_{\st{nd}\;i}$ are the eigenvalues of the strain if the material were undamaged. The coefficients $A$ and $B$ are the post-peak asymptotic value and the decay shape parameters. \IfFileExists{manual-constitutive-laws-non_local.tex}{\input{manual-constitutive-laws-non_local.tex}}{} \IfFileExists{manual-extra_materials.tex}{\input{manual-extra_materials}}{} \IfFileExists{manual-cohesive_laws.tex}{\input{manual-cohesive_laws}}{} %%% Local Variables: %%% mode: latex %%% TeX-master: "manual" %%% End: diff --git a/doc/manual/manual-gettingstarted.tex b/doc/manual/manual-gettingstarted.tex index b489654c0..4135c1cf1 100644 --- a/doc/manual/manual-gettingstarted.tex +++ b/doc/manual/manual-gettingstarted.tex @@ -1,326 +1,424 @@ \chapter{Getting Started} \section{Downloading the Code} The \akantu source code can be requested using the form accessible at the URL \url{http://lsms.epfl.ch/akantu}. There, you will be asked to accept the LGPL license terms. \section{Compiling \akantu} \akantu is a \code{cmake} project, so to configure it, you can either follow the usual way: \begin{command} > cd akantu > mkdir build > cd build > ccmake .. [ Set the options that you need ] > make > make install \end{command} \noindent Or, use the \code{Makefile} we added for your convenience to handle the \code{cmake} configuration \begin{command} > cd akantu > make config > make > make install \end{command} \noindent All the \akantu options are documented in Appendix \ref{app:package-dependencies}. \section{Writing a \texttt{main} Function\label{sect:common:main}} \label{sec:writing_main} First of all, \akantu needs to be initialized. The memory management included in the core library handles the correct allocation and de-allocation of vectors, structures and/or objects. Moreover, in parallel computations, the initialization procedure performs the communication setup. This is achieved by a pair of functions (\code{initialize} and \code{finalize}) that are used as follows: \begin{cpp} #include "aka_common.hh" #include "..." using namespace akantu; int main(int argc, char *argv[]) { initialize("material.dat", argc, argv); // your code ... finalize(); } \end{cpp} The \code{initialize} function takes the material file and the program parameters which can be interpreted by \akantu in due form. Obviously it is necessary to include all files needed in main. In this manual all provided code implies the usage of \code{akantu} as namespace. \section{Creating and Loading a Mesh\label{sect:common:mesh}} In its current state, \akantu supports three types of meshes: Gmsh~\cite{gmsh}, Abaqus~\cite{abaqus} and Diana~\cite{diana}. Once a \code{Mesh} object is created with a given spatial dimension, it can be filled by reading a mesh input file. The method \code{read} of the class \code{Mesh} infers the mesh type from the file extension. If a non-standard file extension is used, the mesh type has to be specified. \begin{cpp} UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); // Reading Gmsh files mesh.read("my_gmsh_mesh.msh"); mesh.read("my_gmsh_mesh", _miot_gmsh); // Reading Abaqus files mesh.read("my_abaqus_mesh.inp"); mesh.read("my_abaqus_mesh", _miot_abaqus); // Reading Diana files mesh.read("my_diana_mesh.dat"); mesh.read("my_diana_mesh", _miot_diana); \end{cpp} The Gmsh reader adds the geometrical and physical tags as mesh data. The physical values are stored as a \code{UInt} data called \code{tag\_0}, if a string name is provided it is stored as a \code{std::string} data named \code{physical\_names}. The geometrical tag is stored as a \code{UInt} data named \code{tag\_1}. The Abaqus reader stores the \code{ELSET} in ElementGroups and the \code{NSET} in NodeGroups. The material assignment can be retrieved from the \code{std::string} mesh data named \code{abaqus\_material}. % \akantu supports meshes generated with Gmsh~\cite{gmsh}, a free % software available at \url{http://geuz.org/gmsh/} where a detailed % documentation can be found. Consequently, this manual will not provide % Gmsh usage directions. Gmsh outputs meshes in \code{.msh} format that can be read % by \akantu. In order to import a mesh, it is necessary to create % a \code{Mesh} object through the following function calls: % \begin{cpp} % UInt spatial_dimension = 2; % Mesh mesh(spatial_dimension); % \end{cpp} % The only parameter that has to be specified by the user is the spatial % dimension of the problem. Now it is possible to read a \code{.msh} file with % a \code{MeshIOMSH} object that takes care of loading a mesh to memory. % This step is carried out by: % \begin{cpp} % mesh.read("square.msh"); % \end{cpp} % where the \code{MeshIOMSH} object is first created before being % used to read the \code{.msh} file. The mesh file name as well as the \code{Mesh} % object must be specified by the user. % The \code{MeshIOMSH} object can also write mesh files. This feature % is useful to save a mesh that has been modified during a % simulation. The \code{write} method takes care of it: % \begin{cpp} % mesh_io.write("square_modified.msh", mesh); % \end{cpp} % which works exactly like the \code{read} method. % \akantu supports also meshes generated by % DIANA (\url{http://tnodiana.com}), but only in reading mode. A similar % procedure applies where the only % difference is that the \code{MeshIODiana} object should be used % instead of the \code{MeshIOMSH} one. Additional mesh readers can be % introduced into \akantu by coding new \code{MeshIO} classes. \section{Using \texttt{Arrays}} Data in \akantu can be stored in data containers implemented by the \code{Array} class. In its most basic usage, the \code{Array} class implemented in \akantu is similar to the \code{vector} class of the Standard Template Library (STL) for C++. A simple \code{Array} containing a sequence of \code{nb\_element} values can be generated with: \begin{cpp} Array example_array(nb_element); \end{cpp} where \code{type} usually is \code{Real}, \code{Int}, \code{UInt} or \code{bool}. Each value is associated to an index, so that data can be accessed by typing: \begin{cpp} type & val = example_array(index) \end{cpp} \code{Arrays} can also contain tuples of values for each index. In that case, the number of components per tuple must be specified at the \code{Array} creation. For example, if we want to create an \code{Array} to store the coordinates (sequences of three values) of ten nodes, the appropriate code is the following: \begin{cpp} UInt nb_nodes = 10; UInt spatial_dimension = 3; Array position(nb_nodes, spatial_dimension); \end{cpp} In this case the $x$ position of the eighth node number will be given by \code{position(7, 0)} (in C++, numbering starts at 0 and not 1). If the number of components for the sequences is not specified, the default value of 1 is used. It is very common in \akantu to loop over arrays to perform a specific treatment. This ranges from geometric calculation on nodal quantities to tensor algebra (in constitutive laws for example). The \code{Array} object has the possibility to request iterators in order to make the writing of loops easier and enhance readability. For instance, a loop over the nodal coordinates can be performed like: \begin{cpp} //accessing the nodal coordinates Array Array nodes = mesh.getNodes(); //creating the iterators Array::vector_iterator it = nodes.begin(spatial_dimension); Array::vector_iterator end = nodes.end(spatial_dimension); for (; it != end; ++it){ Vector & coords = (*it); //do what you need .... } \end{cpp} In that example, each \code{Vector} is a geometrical array of size \code{spatial\_dimension} and the iteration is conveniently performed by the \code{Array} iterator. The \code{Array} object is intensively used to store second order tensor values. In that case, it should be specified that the returned object type is a matrix when constructing the iterator. This is done when calling the \code{begin} function. For instance, assuming that we have a \code{Array} storing stresses, we can loop over the stored tensors by: \begin{cpp} //creating the iterators Array::matrix_iterator it = stresses.begin(spatial_dimension,spatial_dimension); Array::matrix_iterator end = stresses.end(spatial_dimension,spatial_dimension); for (; it != end; ++it){ Matrix & stress = (*it); //do what you need .... } \end{cpp} In that last example, the \code{Matrix} objects are \code{spatial\_dimension} $\times$ \code{spatial\_dimension} matrices. The light objects \code{Matrix} and \code{Vector} can be used and combined to do most common linear algebra. In general, a mesh consists of several kinds of elements. Consequently, the amount of data to be stored can differ for each element type. The straightforward example is the connectivity array, namely the sequences of nodes belonging to each element (linear triangular elements have fewer nodes than, say, rectangular quadratic elements etc.). A particular data structure called \code{ElementTypeMapArray} is provided to easily manage this kind of data. It consists of a group of \code{Arrays}, each associated to an element type. The following code can retrieve the \code{ElementTypeMapArray} which stores the connectivity arrays for a mesh: \begin{cpp} ElementTypeMapArray & connectivities = mesh.getConnectivities(); \end{cpp} Then, the specific array associated to a given element type can be obtained by \begin{cpp} Array & connectivity_triangle = connectivities(_triangle_3); \end{cpp} where the first order 3-node triangular element was used in the presented piece of code. -\section{Manipulating group of nodes and/or elements} +\subsection{Vector \& Matrix} + +The \code{Array} iterators as presented in the previous section can be shaped as +\code{Vector} or \code{Matrix}. This objects represent $1^{st}$ and $2^{nd}$ +order tensors. As such they come with some functionalities that we will present +a bit more into detail in this here. + +\subsubsection{\texttt{Vector}} + +\begin{enumerate} +\item Accessors: + \begin{itemize} + \item \code{v(i)} gives the $i^{th}$ component of the vector \code{v} + \item \code{v[i]} gives the $i^{th}$ component of the vector \code{v} + \item \code{v.size()} gives the number of component + \end{itemize} +\item Level 1: (results are scalars) + \begin{itemize} + \item \code{v.norm()} returns the geometrical norm ($L_2$) + \item \code{v.norm()} returns the $L_N$ norm defined as $\left(\sum_i + |\code{v(i)}|^N\right)^{1/N}$. N can take any positive + integer value. There are also some particular values for the most commonly + used norms, \code{L\_1} for the Manhattan norm, \code{L\_2} for the + geometrical norm and \code{L\_inf} for the norm infinity. + \item \code{v.dot(x)} return the dot product of \code{v} and \code{x} + \item \code{v.distance(x)} return the geometrical norm of $\code{v} - + \code{x}$ + \end{itemize} +\item Level 2: (results are vectors) + \begin{itemize} + \item \code{v += s}, \code{v -= s}, \code{v *= s}, \code{v /= s} those are + element-wise operators that sum, substract, multiply or divide all the + component of \code{v} by the scalar \code{s} + \item \code{v += x}, \code{v -= x} sums or substracts the vector \code{x} + to/from \code{v} + \item \code{v.mul(A, x, alpha)} stores the result of $\alpha \mat{A} \vec{x}$ in \code{v}, + $\alpha$ is equal to 1 by default + \item \code{v.solve(A, b)} stores the result of the resolution of the system $\mat{A} \vec{x} = + \vec{b}$ in \code{v} + \item \code{v.crossProduct(v1, v2)} computes the cross product of \code{v1} and \code{v2} and + stores the result in \code{v} + \end{itemize} +\end{enumerate} + +\subsubsection{\texttt{Matrix}} +\begin{enumerate} +\item Accessors: + \begin{itemize} + \item \code{A(i, j)} gives the component $A_{ij}$ of the matrix \code{A} + \item \code{A(i)} gives the $i^{th}$ column of the matrix as a \code{Vector} + \item \code{A[k]} gives the $k^{th}$ component of the matrix, matrices are + stored in a column major way, which means that to access $A_{ij}$, $k = i + + j M$ + \item \code{A.rows()} gives the number of rows of \code{A} ($M$) + \item \code{A.cols()} gives the number of columns of \code{A} ($N$) + \item \code{A.size()} gives the number of component in the matrix ($M \times N$) + \end{itemize} +\item Level 1: (results are scalars) + + \begin{itemize} + \item \code{A.norm()} returns the $L_N$ norm defined as $\left(\sum_i + |\code{A(i)}|^N\right)^{1/N}$. N can take any positive + integer value. + \item \code{A.norm()} is equivalent to \code{A.norm()} + \item \code{A.trace()} return the trace of \code{A} + \item \code{A.det()} return the determinant of \code{A} + \item \code{A.doubleDot(B)} return the double dot product of \code{A} and + \code{B}, $\mat{A}:\mat{B}$ + \end{itemize} +\item Level 3: (results are matrices) + \begin{itemize} + \item \code{A.eye(s)}, \code{Matrix::eye(s)} fills/creates a matrix with + the $s\mat{I}$ with $\mat{I}$ the identity matrix + \item \code{A.inverse(B)} stores $\mat{B}^{-1}$ in \code{A} + \item \code{A.transpose()} returns $\mat{A}^{t}$ + \item \code{A.outerProduct(v1, v2)} stores $\vec{v_1} \vec{v_2}^{t}$ in + \code{A} + \item \code{C.mul(A, B, alpha)}: stores the result of the product of + \code{A} and code{B} time the scalar \code{alpha} in \code{C}. \code{t\_A} + and \code{t\_B} are boolean defining if \code{A} and \code{B} should be + transposed or not. + + \begin{tabular}{ccl} + \toprule + \code{t\_A} & \code{t\_B} & result \\ + \midrule + false & false & $\mat{C} = \alpha \mat{A} \mat{B}$\\ + false & true & $\mat{C} = \alpha \mat{A} \mat{B}^t$\\ + true & false & $\mat{C} = \alpha \mat{A}^t \mat{B}$\\ + true & true & $\mat{C} = \alpha \mat{A}^t \mat{B}^t$\\ + \bottomrule + \end{tabular} + \item \code{A.eigs(d, V)} this method computes the eigenvalues and + eigenvectors of \code{A} and store the results in \code{d} and \code{V} such + that $\code{d(i)} = \lambda_i$ and $\code{V(i)} = \vec{v_i}$ with + $\mat{A}\vec{v_i} = \lambda_i\vec{v_i}$ and $\lambda_1 > ... > \lambda_i > + ... > \lambda_N$ + \end{itemize} +\end{enumerate} + -\akantu provides the possibility to manipulate +\section{Manipulating group of nodes and/or elements} +\akantu provides the possibility to manipulate subgroups of elements and nodes. -Any \code{ElementGroup} and/or \code{NodeGroup} must be managed -by a \code{GroupManager}. Such a manager has the role to -associate group objects to names. This is a useful feature, -in particular for the application of the boundary conditions, +Any \code{ElementGroup} and/or \code{NodeGroup} must be managed +by a \code{GroupManager}. Such a manager has the role to +associate group objects to names. This is a useful feature, +in particular for the application of the boundary conditions, as will be demonstrated in section \ref{sect:smm:boundary}. -To most general group manager is the \code{Mesh} class +To most general group manager is the \code{Mesh} class which inheritates from the \code{GroupManager} class. For instance, the following code shows how to request an element group to a mesh: \begin{cpp} // request creation of a group of nodes NodeGroup & my_node_group = mesh.createNodeGroup("my_node_group"); // request creation of a group of elements ElementGroup & my_element_group = mesh.createElementGroup("my_element_group"); /* fill and use the groups */ \end{cpp} \subsection{The \texttt{NodeGroup} object} - A group of nodes is stored in \code{NodeGroup} objects. They are quite simple objects which store the indexes -of the selected nodes in a \code{Array}. -Nodes are selected by adding them when calling -\code{NodeGroup::add}. For instance you can select nodes +of the selected nodes in a \code{Array}. +Nodes are selected by adding them when calling +\code{NodeGroup::add}. For instance you can select nodes having a positive $X$ coordinate with the following code: \begin{cpp} Array & nodes = mesh.getNodes(); NodeGroup & group = mesh.createNodeGroup("XpositiveNode"); Array::const_vector_iterator it = nodes.begin(spatial_dimension); Array::const_vector_iterator end = nodes.end(spatial_dimension); UInt index = 0; for (; it != end ; ++it , ++index){ - const Vector & position = *it; + const Vector & position = *it; if (position(0) > 0) group.add(index); - } + } \end{cpp} \subsection{The \texttt{ElementGroup} object} - A group of elements is stored in \code{ElementGroup} objects. -Since a group can contain elements of various types -the \code{ElementGroup} object stores indexes in +Since a group can contain elements of various types +the \code{ElementGroup} object stores indexes in a \code{ElementTypeMapArray} object. Then elements can be added to the group by calling \code{addElement}. For instance, selecting the elements for which the barycenter of the nodes has a positive $X$ coordinate can be made with: \begin{cpp} ElementGroup & group = mesh.createElementGroup("XpositiveElement"); Mesh::type_iterator it = mesh.firstType(); Mesh::type_iterator end = mesh.lastType(); Vector barycenter(spatial_dimension); for(; it != end; ++it){ UInt nb_element = mesh.getNbElement(*it); for(UInt e = 0; e < nb_element; ++e) { ElementType type = *it; mesh.getBarycenter(e, type, barycenter.storage()); - if (barycenter(0) > 0) group.add(type,e); + if (barycenter(0) > 0) group.add(type,e); } - } + } \end{cpp} %%% Local Variables: %%% mode: latex %%% TeX-master: "manual" %%% End: diff --git a/doc/manual/manual.sty b/doc/manual/manual.sty index a49f60246..6855a85ab 100644 --- a/doc/manual/manual.sty +++ b/doc/manual/manual.sty @@ -1,309 +1,312 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% %% LaTeX STYLE SHEET for AKANTU DOCUMENTATION %% %% %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Geometry \usepackage{a4wide} \usepackage{geometry} \geometry{ pdftex=true, twoside=true, margin=20mm, bottom=20mm, top=20mm, bindingoffset=5.5mm } % Font encoding \usepackage[T1]{fontenc} \usepackage{palatino} % Line spacing \linespread{1.05}\selectfont % Allow spaces to be added at the end of macro \usepackage{xspace} % Mathematics (including correct font encoding, after amsmath) \usepackage{amsmath} \usepackage{amssymb} \usepackage{pxfonts} \setlength\mathindent{2em} % Some unit stuff \usepackage{siunitx} % Easy tables \usepackage{booktabs} \usepackage{longtable} \usepackage{rotating} % For sideways tables \usepackage{multirow} % For larger cells % A special environment for element tables \newcommand\elemline{}%{\noalign{\smallskip}\hline\noalign{\smallskip}} \newcommand\elemcooroned{\ensuremath{\left(\xi\right)}} \newcommand\elemcoortwod{\ensuremath{\left(\xi\;,\;\eta\right)}} \newcommand\elemcoorthreed{\ensuremath{\left(\xi\;,\;\eta\;,\;\zeta\right)}} \newcommand\elemdshapeoned{\ensuremath{\left(\partial N_i/\partial\xi\right)}} \newcommand\elemdshapetwod{\ensuremath{\left(\partial N_i/\partial\xi\;,\;\partial N_i/\partial\eta\right)}} \newcommand\elemdshapethreed{\ensuremath{\left(\partial N_i/\partial\xi\;,\;\partial N_i/\partial\eta\;,\;\partial N_i/\partial\zeta\right)}} \newcommand\inelemone[1]{\ensuremath{#1}} %\newcommand\inelemtwo[2]{\ensuremath{\begin{pmatrix} {\; #1} & \!,\! & {#2 \;} \end{pmatrix}}} %\newcommand\inelemthree[3]{\ensuremath{\begin{pmatrix} {\; #1} & \!,\! & {#2} & \!,\! & {#3 \;} \end{pmatrix}}} \newcommand\inelemtwo[2]{\ensuremath{\left( {\; #1} \; , \; {#2 \;} \right)}} \newcommand\inelemthree[3]{\ensuremath{\left( {\; #1} \; , \; {#2} \; , \; {#3 \;} \right)}} \newcommand\inelemthreecolumn[3]{\ensuremath{\begin{array}{c}( {\; #1} \; ,\\{#2} \; ,\\{#3 \;} )\end{array}}} \newcommand\inquadone[1]{\ensuremath{#1}} \newcommand\inquadtwo[2]{\ensuremath{\left(\, #1 \, , \, #2 \,\right)}} \newcommand\inquadthree[3]{\ensuremath{\left(\, #1 \, , \, #2 \, , \, #3 \,\right)}} %\newcommand\quada{\tfrac{1}{20}\left(5-\sqrt{5}\right)} %\newcommand\quadb{\tfrac{1}{20}\left(5+3\sqrt{5}\right)} \newcommand\quada{\tfrac{\left(5-\sqrt{5}\right)}{20}} \newcommand\quadb{\tfrac{\left(5+3\sqrt{5}\right)}{20}} \newenvironment{Element}[1] {%\begin{table*}[!htbp] \footnotesize \ifthenelse{\equal{#1}{1D}}{\renewcommand{\arraystretch}{1.50}}{} \ifthenelse{\equal{#1}{2D}}{\renewcommand{\arraystretch}{1.60}}{} \ifthenelse{\equal{#1}{3D}}{\renewcommand{\arraystretch}{1.70}}{} \textbf{{\normalsize Element properties}}\\%\vspace*{0.5\baselineskip} \begin{tabular}{cccc}\\[-2ex] \toprule % \multicolumn{4}{l}{\textbf{{\normalsize Element properties}}} \\ - Node ($i$) & Coord. + Node ($i$) & Coord. \ifthenelse{\equal{#1}{1D}}{\elemcooroned}{} \ifthenelse{\equal{#1}{2D}}{\elemcoortwod}{} \ifthenelse{\equal{#1}{3D}}{\elemcoorthreed}{} & Shape function ($N_{i}$) & {Derivative \ifthenelse{\equal{#1}{1D}}{\elemdshapeoned}{} \ifthenelse{\equal{#1}{2D}}{\elemdshapetwod}{} \ifthenelse{\equal{#1}{3D}}{\elemdshapethreed}{} }\\ \midrule \elemline } {\bottomrule \end{tabular}%\end{table*} } \newenvironment{QuadPoints}[1] {\vspace*{\baselineskip} %\begin{table*}[!htbp] \footnotesize \renewcommand{\arraystretch}{1.50} \noindent\textbf{{\normalsize Gaussian quadrature points}}\newline%\vspace*{0.5\baselineskip} \begin{tabular}{#1}\\[-2ex] \toprule } {\bottomrule\end{tabular}}%\end{table*}} %\usepackage{xparse} \newenvironment{MaterialDesc}[2]{ +\label{#2-app} Keyword: \code{#1}\par \noindent Description here: \ref{#2}\par \noindent Parameters:\par \vspace*{-.4cm} \begin{itemize} \setlength{\topsep}{0ex}% \setlength{\parsep}{0cm}% \setlength{\itemsep}{0cm}% \setlength{\parskip}{0cm}% }{\end{itemize}} \newcommand{\matparam}[3]{\item \code{#1}: (\emph{#2}) #3} \newcommand{\matinherit}[1]{\usebox{#1}} - +\newcommand{\matlabel}[1]{\label{#1}\xspace(\ref{#1-app})} % Nice coloring \usepackage[dvipsnames,usenames,table]{xcolor} \definecolor{RED}{rgb}{1,0,0} \definecolor{cppbg}{HTML}{EBF2F2} \definecolor{shellbg}{HTML}{F5EDE4} \definecolor{commentcolor}{HTML}{101280} % Allow for the use of listings \usepackage{listings} % Create an index \usepackage{makeidx} % Figure handling \usepackage{graphics} \usepackage{epsfig} \usepackage[lofdepth,lotdepth]{subfig} \usepackage{tikz} \usetikzlibrary{decorations} +\usepackage{wrapfig} + \renewcommand{\floatpagefraction}{.6} % default: .5 \renewcommand\topfraction{0.9} % 90% of page top can be a float (Standard 0.7) \renewcommand\bottomfraction{0.1} % 10% of page bottom can be a float (Standard 0.3) \renewcommand\textfraction{0.1} % only 10% of page must to be text (Standard 0.2) % Removes parenthese around subfig number -\renewcommand*{\thesubfigure}{\alph{subfigure}} +\renewcommand*{\thesubfigure}{\alph{subfigure}} % Create a new list style for C++ \lstdefinestyle{C++}{ language=C++, % the language of the code basicstyle=\small\ttfamily, % Without beramono, we'd get cmtt, the teletype font. commentstyle=\color{commentcolor}\itshape, keywordstyle=\color{DarkOrchid}\bfseries, % fontadjust, % numbers=left, % where to put the line-numbers % numberstyle=\tiny, % the size of the fonts that are used for the line-numbers % stepnumber=2, % the step between two line-numbers. If it's 1, each line will % be numbered % numbersep=5pt, % how far the line-numbers are from the code % showspaces=false, % show spaces adding particular underscores showstringspaces=false, % underline spaces within strings % showtabs=false, % show tabs within strings adding particular underscores % frame=llines, % adds a frame around the code % frame=tb, tabsize=2, % sets default tabsize to 2 spaces captionpos=b, % sets the caption-position to bottom breaklines=true, % sets automatic line breaking breakatwhitespace=false, % sets if automatic breaks should only happen at % whitespace % title=\lstname, % show the filename of files included with \lstinputlisting; % also try caption instead of title % escapeinside={\%*}{*)}, % if you want to add a comment within your code xleftmargin=1cm, xrightmargin=1cm, mathescape=true, escapechar=\%, morekeywords={Real, UInt, Int}, columns=flexible, keepspaces=true, backgroundcolor=\color{cppbg} } % Create new list style for the shell \lstdefinestyle{shell}{ language=bash, % the language of the code basicstyle=\scriptsize\ttfamily, % Without beramono, we'd get cmtt, the teletype font. showstringspaces=false, % underline spaces within strings tabsize=2, % sets default tabsize to 2 spaces captionpos=b, % sets the caption-position to bottom breaklines=true, % sets automatic line breaking breakatwhitespace=false, xleftmargin=1cm, xrightmargin=1cm, escapechar=\%, morekeywords={mkdir, make, ccmake, cmake}, columns=flexible, keepspaces=true, backgroundcolor=\color{shellbg} } % Set some derived listing environments \lstnewenvironment{cpp}{\lstset{style=C++}}{} \lstnewenvironment{command}{\lstset{style=shell}}{} % Make sure outputspace is white \makeatletter \def\lst@outputspace{{\ifx\lst@bkgcolor\empty\color{white}\else\lst@bkgcolor\fi\lst@visiblespace}} \makeatother % Renow a label in the itemized lists \renewcommand{\labelitemi}{$\mathbf{\circ}$} % Don't care so much about overfull h-boxes \sloppy % Penalty adjusments %\widowpenalty=10000 % Single lines/word on beginning of page %\clubpenalty=10000 % Single lines/word at end of page %\hyphenpenalty=2000 % Hyphenate words %\tolerance=250 % To adjust the hyphenation of words, increase the tolerance to discourage hyphenation % the higher the value, the more ugly the gaps between words % default \tolerance=200 %\hfuzz=10000pt % threshold when an overfull hbox is reported, default \hfuzz=0.1pt %\vfuzz=10000pt % threshold to report an overfull vbox, default \vfuzz=0.1pt %\hbadness=10000 % threshold to report an underfull \hbox %\vbadness=10000 % threshold to report an underfull \vbox protokolliert wird. \emergencystretch=0pt % causes a third attempt to fix bad paragraphs and defines a maximum limit to stretch them % Insert an empty or a blank page \newcommand{\insertemptypage}{\newpage\hbox{}\newpage} \newcommand{\insertblankpage}{\newpage\thispagestyle{empty}\hbox{}\newpage} % No page number on an empty page \let\origdoublepage\cleardoublepage \newcommand{\clearemptydoublepage}{% \clearpage {\thispagestyle{empty}\origdoublepage}% } \let\cleardoublepage\clearemptydoublepage % A new ruler for in chapters \newcommand\InChapterRule{\addvspace{\baselineskip}\rule{0.3\linewidth}{0.25pt}} % New footnote style %\def\@fnsymbol#1{\ifcase#1\or *\or \dagger\or \ddagger\or \mathchar "278\or \mathchar "27B\or \|\or **\or \dagger\dagger \or \ddagger\ddagger \else\@ctrerr\fi\relax} \def\@fnsymbol#1{*\xspace\relax} \renewcommand{\thefootnote}{\fnsymbol{footnote}} % Symbols rather than numbers \def\footnoterule{\vspace*{0.5\baselineskip}\InChapterRule\vspace*{0.25\baselineskip}} % Improved look of the Table of Contents \usepackage[nottoc,notbib]{tocbibind} \usepackage[dotinlabels]{titletoc} \titlecontents{chapter}[1.4pc] {\addvspace{0.6pc}\large\bfseries\filright} {\contentslabel[\thecontentslabel.]{1.4pc}} {\hspace{-1.4pc}} {\hfill\contentspage} [\addvspace{2pt}] \titlecontents{section}[3.4pc] {\filright} {\contentslabel[\thecontentslabel]{2pc}} {\hspace{-2pc}} {\titlerule*[6pt]{.}\contentspage} [] \titlecontents{subsection}[5.0pc] {\filright} {\contentslabel[\thecontentslabel]{2.4pc}} {} {\titlerule*[6pt]{.}\contentspage} [] \setcounter{tocdepth}{2} \newcommand\addspaceintoc{\addtocontents{toc}{\protect\addvspace{20pt}}} % Change the appearance of the bibliography \bibliographystyle{manual-bibliographystyle} \renewcommand\bibname{References} \usepackage{cite} % To sort citations: [2,10-14] \let\oldthebibliography=\thebibliography \let\endoldthebibliography=\endthebibliography \renewenvironment{thebibliography}[1] { \begin{oldthebibliography}{#1} % \small \addcontentsline{toc}{chapter}{\bibname} \setlength{\labelsep}{2mm} \setlength{\parskip}{0\baselineskip} \setlength{\itemsep}{0.24\baselineskip} } { \end{oldthebibliography} } % Hyperref \usepackage{url} \usepackage[pdftex, bookmarks=true, bookmarksnumbered=true, % linkbordercolor={1 1 1}, % pdfborder={0 0 0}, pdfpagemode=UseOutlines ]{hyperref} \hypersetup{ pdfauthor={Computational Solid Mechanics Laboratory - EPFL}, pdftitle={Akantu User's Guide}, pdfsubject={Open Source Finite Element Code - Akantu} } \newenvironment{AkantuPackage}[2]{% \paragraph*{#1}\label{#2} }{} \newenvironment{AkantuPackageDependencies}{\emph{Dependencies}: }{} \newcommand\AkantuPackageNameWithLabel[3]{\textit{\index{Packages!#1}\hyperref[#2]{#1}}\xspace} \newcommand\akantuManualAppendix[1]{} \ No newline at end of file diff --git a/doc/manual/manual.tex b/doc/manual/manual.tex index 025fa6d5c..f9cd426e9 100644 --- a/doc/manual/manual.tex +++ b/doc/manual/manual.tex @@ -1,47 +1,47 @@ \documentclass[openright,a4paper,11pt,fleqn]{manual} \usepackage{manual} \usepackage{manual-macros} -\newcommand{\version}{2.2pre1} +\newcommand{\version}{} \graphicspath{ {./figures/} } %%% For references \todo check the coherency %% section 3.5 -> Section 3.5 %% figure 3.5 -> Figure 3.5 %% equation 3.5 -> Equation (3.5) % Title pages and Table of Contents (includes \begin{document}) \input{manual-titlepages} % Introduction chapter \input{manual-introduction} % The planning to write the documentation %\input{manual-planning} % The documentation chapter (split in parts) \input{manual-gettingstarted} \input{manual-elements} %\IfFileExists{manual-lumping.tex}{}{\input{manual-lumping}} \input{manual-solidmechanicsmodel} \IfFileExists{manual-structuralmechanicsmodel.tex}{\input{manual-structuralmechanicsmodel}}{} \IfFileExists{manual-heattransfermodel.tex}{\input{manual-heattransfermodel}}{} \input{manual-io} \IfFileExists{manual-parallel.tex}{\input{manual-parallel}}{} \IfFileExists{manual-contact.tex}{\input{manual-contact}}{} % The appendices \appendix \input{manual-appendix-elements} \input{manual-appendix-materials} \input{manual-appendix-packages} % The backmatter material (index/bibliography, included \end{document}) \input{manual-backmatter} diff --git a/packages/00_core.cmake b/packages/00_core.cmake index 14d466157..3364f3ed4 100644 --- a/packages/00_core.cmake +++ b/packages/00_core.cmake @@ -1,490 +1,437 @@ #=============================================================================== # @file core.cmake # # @author Guillaume Anciaux # @author Nicolas Richart # # @date Mon Nov 21 18:19:15 2011 # # @brief package description for core # # @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 . # #=============================================================================== set(AKANTU_CORE ON CACHE INTERNAL "core package for Akantu" FORCE) set(AKANTU_CORE_FILES common/aka_array.cc common/aka_array.hh common/aka_array_tmpl.hh common/aka_blas_lapack.hh common/aka_circular_array.hh common/aka_circular_array_inline_impl.cc common/aka_common.cc common/aka_common.hh common/aka_common_inline_impl.cc common/aka_csr.hh common/aka_error.cc common/aka_error.hh common/aka_event_handler_manager.hh common/aka_extern.cc common/aka_fwd.hh common/aka_grid_dynamic.hh common/aka_math.cc common/aka_math.hh common/aka_math_tmpl.hh common/aka_memory.cc common/aka_memory.hh common/aka_memory_inline_impl.cc common/aka_random_generator.hh common/aka_safe_enum.hh common/aka_static_memory.cc common/aka_static_memory.hh common/aka_static_memory_inline_impl.cc common/aka_static_memory_tmpl.hh common/aka_typelist.hh common/aka_types.hh common/aka_visitor.hh common/aka_voigthelper.hh common/aka_voigthelper.cc fe_engine/element_class.cc fe_engine/element_class.hh fe_engine/element_class_tmpl.hh fe_engine/element_classes/element_class_hexahedron_8_inline_impl.cc fe_engine/element_classes/element_class_pentahedron_6_inline_impl.cc fe_engine/element_classes/element_class_point_1_inline_impl.cc fe_engine/element_classes/element_class_quadrangle_4_inline_impl.cc fe_engine/element_classes/element_class_quadrangle_8_inline_impl.cc fe_engine/element_classes/element_class_segment_2_inline_impl.cc fe_engine/element_classes/element_class_segment_3_inline_impl.cc fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.cc fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.cc fe_engine/element_classes/element_class_triangle_3_inline_impl.cc fe_engine/element_classes/element_class_triangle_6_inline_impl.cc fe_engine/fe_engine.cc fe_engine/fe_engine.hh fe_engine/fe_engine_inline_impl.cc fe_engine/fe_engine_template.hh fe_engine/fe_engine_template_tmpl.hh fe_engine/geometrical_data_tmpl.hh fe_engine/geometrical_element.cc fe_engine/integration_element.cc fe_engine/integrator.hh fe_engine/integrator_gauss.hh fe_engine/integrator_gauss_inline_impl.cc fe_engine/interpolation_element.cc fe_engine/interpolation_element_tmpl.hh fe_engine/shape_functions.hh fe_engine/shape_functions_inline_impl.cc fe_engine/shape_lagrange.cc fe_engine/shape_lagrange.hh fe_engine/shape_lagrange_inline_impl.cc fe_engine/shape_linked.cc fe_engine/shape_linked.hh fe_engine/shape_linked_inline_impl.cc fe_engine/element.hh - -# fem/by_element_type.hh - -# fem/by_element_type_tmpl.hh -# -# fem/element_class.cc -# fem/element_class.hh -# fem/element.hh -# fem/element_class_tmpl.hh -# fem/element_classes/element_class_hexahedron_8_inline_impl.cc -# fem/element_classes/element_class_pentahedron_6_inline_impl.cc -# fem/element_classes/element_class_point_1_inline_impl.cc -# fem/element_classes/element_class_quadrangle_4_inline_impl.cc -# fem/element_classes/element_class_quadrangle_8_inline_impl.cc -# fem/element_classes/element_class_segment_2_inline_impl.cc -# fem/element_classes/element_class_segment_3_inline_impl.cc -# fem/element_classes/element_class_tetrahedron_10_inline_impl.cc -# fem/element_classes/element_class_tetrahedron_4_inline_impl.cc -# fem/element_classes/element_class_triangle_3_inline_impl.cc -# fem/element_classes/element_class_triangle_6_inline_impl.cc -# -# fem/element_group.cc -# fem/element_group.hh -# fem/element_group_inline_impl.cc -# fem/fem.cc -# fem/fem.hh -# fem/fem_inline_impl.cc -# fem/fem_template.hh -# fem/fem_template_tmpl.hh -# fem/geometrical_data_tmpl.hh -# fem/geometrical_element.cc -# fem/group_manager.cc -# fem/group_manager.hh -# fem/group_manager_inline_impl.cc -# fem/integration_element.cc -# fem/integrator.hh -# fem/integrator_gauss.hh -# fem/integrator_gauss_inline_impl.cc -# fem/interpolation_element.cc -# fem/interpolation_element_tmpl.hh -# fem/mesh.cc -# fem/mesh.hh -# fem/mesh_filter.hh -# fem/mesh_data.cc -# fem/mesh_data.hh -# fem/mesh_data_tmpl.hh -# fem/mesh_inline_impl.cc -# fem/node_group.cc -# fem/node_group.hh -# fem/node_group_inline_impl.cc -# fem/shape_functions.hh -# fem/shape_functions_inline_impl.cc -# fem/shape_lagrange.cc -# fem/shape_lagrange.hh -# fem/shape_lagrange_inline_impl.cc -# fem/shape_linked.cc -# fem/shape_linked.hh -# fem/shape_linked_inline_impl.cc - io/dumper/dumpable.hh io/dumper/dumpable.cc io/dumper/dumpable_inline_impl.hh io/dumper/dumper_field.hh io/dumper/dumper_material_padders.hh io/dumper/dumper_filtered_connectivity.hh io/dumper/dumper_element_type.hh io/dumper/dumper_element_partition.hh io/mesh_io.cc io/mesh_io.hh io/mesh_io/mesh_io_abaqus.cc io/mesh_io/mesh_io_abaqus.hh io/mesh_io/mesh_io_diana.cc io/mesh_io/mesh_io_diana.hh io/mesh_io/mesh_io_msh.cc io/mesh_io/mesh_io_msh.hh io/model_io.cc io/model_io.hh io/parser/algebraic_parser.hh io/parser/input_file_parser.hh io/parser/parsable.cc io/parser/parsable.hh io/parser/parsable_tmpl.hh io/parser/parser.cc io/parser/parser.hh io/parser/parser_tmpl.hh io/parser/cppargparse/cppargparse.hh io/parser/cppargparse/cppargparse.cc io/parser/cppargparse/cppargparse_tmpl.hh mesh/element_group.cc mesh/element_group.hh mesh/element_group_inline_impl.cc mesh/element_type_map.hh mesh/element_type_map_tmpl.hh mesh/element_type_map_filter.hh mesh/group_manager.cc mesh/group_manager.hh mesh/group_manager_inline_impl.cc mesh/mesh.cc mesh/mesh.hh mesh/mesh_filter.hh mesh/mesh_data.cc mesh/mesh_data.hh mesh/mesh_data_tmpl.hh mesh/mesh_inline_impl.cc mesh/node_group.cc mesh/node_group.hh mesh/node_group_inline_impl.cc mesh_utils/mesh_partition.cc mesh_utils/mesh_partition.hh mesh_utils/mesh_partition/mesh_partition_mesh_data.cc mesh_utils/mesh_partition/mesh_partition_mesh_data.hh mesh_utils/mesh_partition/mesh_partition_scotch.hh mesh_utils/mesh_pbc.cc mesh_utils/mesh_utils.cc mesh_utils/mesh_utils.hh mesh_utils/mesh_utils_inline_impl.cc mesh_utils/mesh_graph.cc mesh_utils/mesh_graph.hh model/boundary_condition.hh model/boundary_condition_functor.hh model/boundary_condition_functor_inline_impl.cc model/boundary_condition_tmpl.hh model/integration_scheme/generalized_trapezoidal.hh model/integration_scheme/generalized_trapezoidal_inline_impl.cc model/integration_scheme/integration_scheme_1st_order.hh model/integration_scheme/integration_scheme_2nd_order.hh model/integration_scheme/newmark-beta.hh model/integration_scheme/newmark-beta_inline_impl.cc model/model.cc model/model.hh model/model_inline_impl.cc model/solid_mechanics/material.cc model/solid_mechanics/material.hh model/solid_mechanics/material_inline_impl.cc model/solid_mechanics/material_list.hh model/solid_mechanics/material_random_internal.hh model/solid_mechanics/material_selector.hh model/solid_mechanics/material_selector_tmpl.hh model/solid_mechanics/materials/internal_field.hh model/solid_mechanics/materials/internal_field_tmpl.hh - model/solid_mechanics/materials/material_elastic.cc - model/solid_mechanics/materials/material_elastic.hh - model/solid_mechanics/materials/material_elastic_inline_impl.cc - model/solid_mechanics/materials/material_thermal.cc - model/solid_mechanics/materials/material_thermal.hh model/solid_mechanics/materials/random_internal_field.hh model/solid_mechanics/materials/random_internal_field_tmpl.hh model/solid_mechanics/solid_mechanics_model.cc model/solid_mechanics/solid_mechanics_model.hh model/solid_mechanics/solid_mechanics_model_inline_impl.cc model/solid_mechanics/solid_mechanics_model_mass.cc model/solid_mechanics/solid_mechanics_model_material.cc model/solid_mechanics/solid_mechanics_model_tmpl.hh model/solid_mechanics/solid_mechanics_model_event_handler.hh model/solid_mechanics/materials/plane_stress_toolbox.hh model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh + model/solid_mechanics/materials/material_elastic.cc + model/solid_mechanics/materials/material_elastic.hh + model/solid_mechanics/materials/material_elastic_inline_impl.cc + model/solid_mechanics/materials/material_thermal.cc + model/solid_mechanics/materials/material_thermal.hh + model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc + model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh + model/solid_mechanics/materials/material_elastic_orthotropic.cc + model/solid_mechanics/materials/material_elastic_orthotropic.hh model/solid_mechanics/materials/material_damage/material_damage.hh model/solid_mechanics/materials/material_damage/material_damage_tmpl.hh model/solid_mechanics/materials/material_damage/material_marigo.cc model/solid_mechanics/materials/material_damage/material_marigo.hh model/solid_mechanics/materials/material_damage/material_marigo_inline_impl.cc model/solid_mechanics/materials/material_damage/material_mazars.cc model/solid_mechanics/materials/material_damage/material_mazars.hh model/solid_mechanics/materials/material_damage/material_mazars_inline_impl.cc model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc model/solid_mechanics/materials/material_finite_deformation/material_neohookean.hh model/solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.cc model/solid_mechanics/materials/material_plastic/material_plastic.cc model/solid_mechanics/materials/material_plastic/material_plastic.hh model/solid_mechanics/materials/material_plastic/material_plastic_inline_impl.cc model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.cc model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.hh + + solver/solver.cc solver/solver.hh solver/sparse_matrix.cc solver/sparse_matrix.hh solver/sparse_matrix_inline_impl.cc synchronizer/communication_buffer.hh synchronizer/communication_buffer_inline_impl.cc synchronizer/data_accessor.cc synchronizer/data_accessor.hh synchronizer/data_accessor_inline_impl.cc synchronizer/distributed_synchronizer.cc synchronizer/distributed_synchronizer.hh synchronizer/distributed_synchronizer_tmpl.hh synchronizer/dof_synchronizer.cc synchronizer/dof_synchronizer.hh synchronizer/dof_synchronizer_inline_impl.cc synchronizer/filtered_synchronizer.cc synchronizer/filtered_synchronizer.hh synchronizer/mpi_type_wrapper.hh synchronizer/pbc_synchronizer.cc synchronizer/pbc_synchronizer.hh synchronizer/real_static_communicator.hh synchronizer/static_communicator.cc synchronizer/static_communicator.hh synchronizer/static_communicator_dummy.hh synchronizer/static_communicator_inline_impl.hh synchronizer/synchronizer.cc synchronizer/synchronizer.hh synchronizer/synchronizer_registry.cc synchronizer/synchronizer_registry.hh ) set(AKANTU_CORE_DEB_DEPEND libboost-dev ) set(AKANTU_CORE_TESTS test_csr test_facet_element_mapping test_facet_extraction_tetrahedron_4 test_facet_extraction_triangle_3 test_grid test_interpolate_stress test_local_material test_material_damage_non_local test_material_thermal test_matrix test_mesh_boundary test_mesh_data test_mesh_io_msh test_mesh_io_msh_physical_names test_mesh_partitionate_mesh_data test_parser test_dumper test_pbc_tweak test_purify_mesh test_solid_mechanics_model_bar_traction2d test_solid_mechanics_model_bar_traction2d_structured test_solid_mechanics_model_bar_traction2d_structured_pbc test_solid_mechanics_model_boundary_condition test_solid_mechanics_model_circle_2 test_solid_mechanics_model_cube3d test_solid_mechanics_model_cube3d_pbc test_solid_mechanics_model_cube3d_tetra10 test_solid_mechanics_model_square test_solid_mechanics_model_material_eigenstrain test_static_memory test_surface_extraction_tetrahedron_4 test_surface_extraction_triangle_3 test_vector test_vector_iterator test_weight test_math test_material_standard_linear_solid_deviatoric_relaxation test_material_standard_linear_solid_deviatoric_relaxation_tension test_material_plasticity ) set(AKANTU_CORE_MANUAL_FILES manual.sty manual.cls manual.tex manual-macros.sty manual-titlepages.tex manual-introduction.tex manual-gettingstarted.tex manual-io.tex manual-solidmechanicsmodel.tex manual-constitutive-laws.tex manual-lumping.tex manual-elements.tex manual-appendix-elements.tex manual-appendix-materials.tex manual-appendix-packages.tex manual-backmatter.tex manual-bibliography.bib manual-bibliographystyle.bst figures/bc_and_ic_example.pdf figures/boundary.pdf figures/boundary.svg figures/dirichlet.pdf figures/dirichlet.svg figures/doc_wheel.pdf figures/doc_wheel.svg figures/dynamic_analysis.png figures/explicit_dynamic.pdf figures/explicit_dynamic.svg figures/static.pdf figures/static.svg figures/hooke_law.pdf figures/hot-point-1.png figures/hot-point-2.png figures/implicit_dynamic.pdf figures/implicit_dynamic.svg figures/insertion.pdf figures/interpolate.pdf figures/interpolate.svg figures/problemDomain.pdf_tex figures/problemDomain.pdf figures/static_analysis.png figures/stress_strain_el.pdf figures/tangent.pdf figures/tangent.svg figures/vectors.pdf figures/vectors.svg figures/stress_strain_neo.pdf figures/visco_elastic_law.pdf figures/isotropic_hardening_plasticity.pdf figures/stress_strain_visco.pdf figures/elements/hexahedron_8.pdf figures/elements/hexahedron_8.svg figures/elements/quadrangle_4.pdf figures/elements/quadrangle_4.svg figures/elements/quadrangle_8.pdf figures/elements/quadrangle_8.svg figures/elements/segment_2.pdf figures/elements/segment_2.svg figures/elements/segment_3.pdf figures/elements/segment_3.svg figures/elements/tetrahedron_10.pdf figures/elements/tetrahedron_10.svg figures/elements/tetrahedron_4.pdf figures/elements/tetrahedron_4.svg figures/elements/triangle_3.pdf figures/elements/triangle_3.svg figures/elements/triangle_6.pdf figures/elements/triangle_6.svg figures/elements/xtemp.pdf ) find_program(READLINK_COMMAND readlink) find_program(ADDR2LINE_COMMAND addr2line) mark_as_advanced(READLINK_COMMAND) mark_as_advanced(ADDR2LINE_COMMAND) include(CheckFunctionExists) check_function_exists(clock_gettime _clock_gettime) if(NOT _clock_gettime) set(AKANTU_USE_OBSOLETE_GETTIMEOFDAY ON) else() set(AKANTU_USE_OBSOLETE_GETTIMEOFDAY OFF) endif() list(APPEND AKANTU_BOOST_COMPONENTS graph ) set(AKANTU_CORE_DOCUMENTATION " This package is the core engine of \\akantu. It depends on: \\begin{itemize} \\item A C++ compiler (\\href{http://gcc.gnu.org/}{GCC} >= 4, or \\href{https://software.intel.com/en-us/intel-compilers}{Intel}). \\item The cross-platform, open-source \\href{http://www.cmake.org/}{CMake} build system. \\item The \\href{http://www.boost.org/}{Boost} C++ portable libraries. \\item The \\href{http://www.zlib.net/}{zlib} compression library. \\end{itemize} Under Ubuntu (14.04 LTS) the installation can be performed using the commands: \\begin{command} > sudo apt-get install build-essential cmake-curses-gui libboost-dev zlib1g-dev \\end{command} Under Mac OS X the installation requires the following steps: \\begin{itemize} \\item Install Xcode \\item Install the command line tools. \\item Install the MacPorts project which allows to automatically download and install opensource packages. \\end{itemize} Then the following commands should be typed in a terminal: \\begin{command} > sudo port install cmake gcc48 boost \\end{command} ") \ No newline at end of file diff --git a/packages/30_extra_materials.cmake b/packages/30_extra_materials.cmake index 06598203d..718d2a6bf 100644 --- a/packages/30_extra_materials.cmake +++ b/packages/30_extra_materials.cmake @@ -1,88 +1,82 @@ #=============================================================================== # @file extra_materials.cmake # # @author Nicolas Richart # # @date Wed Oct 31 16:24:42 2012 # # @brief package description for extra materials list # # @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 . # #=============================================================================== option(AKANTU_EXTRA_MATERIALS "Add the extra list of materials in Akantu" OFF) add_external_package_dependencies(extra_materials lapack) set(AKANTU_EXTRA_MATERIALS_FILES model/solid_mechanics/materials/material_extra_includes.hh model/solid_mechanics/materials/material_damage/material_brittle.cc model/solid_mechanics/materials/material_damage/material_brittle.hh model/solid_mechanics/materials/material_damage/material_brittle_inline_impl.cc model/solid_mechanics/materials/material_damage/material_damage_iterative.cc model/solid_mechanics/materials/material_damage/material_damage_iterative.hh model/solid_mechanics/materials/material_damage/material_damage_iterative_inline_impl.cc model/solid_mechanics/materials/material_damage/material_damage_linear.cc model/solid_mechanics/materials/material_damage/material_damage_linear.hh model/solid_mechanics/materials/material_damage/material_damage_linear_inline_impl.cc model/solid_mechanics/materials/material_damage/material_vreepeerlings.hh model/solid_mechanics/materials/material_damage/material_vreepeerlings_inline_impl.cc model/solid_mechanics/materials/material_damage/material_vreepeerlings_tmpl.hh - model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc - model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh - - model/solid_mechanics/materials/material_elastic_orthotropic.cc - model/solid_mechanics/materials/material_elastic_orthotropic.hh - model/solid_mechanics/materials/material_plastic/material_viscoplastic.cc model/solid_mechanics/materials/material_plastic/material_viscoplastic.hh model/solid_mechanics/materials/material_plastic/material_viscoplastic_inline_impl.cc model/solid_mechanics/materials/material_viscoelastic/material_stiffness_proportional.cc model/solid_mechanics/materials/material_viscoelastic/material_stiffness_proportional.hh ) set(AKANTU_EXTRA_MATERIALS_TESTS ) set(AKANTU_EXTRA_MATERIALS_DOC manual/manual-extra_materials.tex manual/manual-appendix-materials-extra-materials.tex ) set(AKANTU_EXTRA_MATERIALS_MANUAL_FILES manual-extra_materials.tex manual-appendix-materials-extra-materials.tex figures/stress_strain_visco.pdf ) set(AKANTU_EXTRA_MATERIALS_DOCUMENTATION " This package activates additional constitutive laws: \\begin{itemize} \\item Linear anisotropy \\item Linear orthotropy \\item Visco-plastic \\end{itemize} " ) diff --git a/packages/80_cpparray.cmake b/packages/80_cpparray.cmake index 18eb84144..e78ed4313 100644 --- a/packages/80_cpparray.cmake +++ b/packages/80_cpparray.cmake @@ -1,84 +1,84 @@ #=============================================================================== # @file cpp_array.cmake # # @author Guillaume Anciaux # @author Nicolas Richart # # @date Mon Nov 21 18:19:15 2011 # # @brief package description for cpp_array project # # @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 . # #=============================================================================== option(AKANTU_USE_CPPARRAY "Use cpp-array library" OFF) option(AKANTU_USE_THIRD_PARTY_CPPARRAY "Automatic download of the CPP-ARRAY library" ON) mark_as_advanced(AKANTU_USE_THIRD_PARTY_CPPARRAY AKANTU_USE_CPPARRAY) -if(AKANTU_USE_CPPARRAY AND AKANTU_USE_THIRD_PARTY_NLOPT) +if(AKANTU_USE_CPPARRAY AND AKANTU_USE_THIRD_PARTY_CPPARRAY) find_package(Git) if(GIT_FOUND) if(EXISTS ${PROJECT_SOURCE_DIR}/third-party/cpp-array) execute_process( COMMAND ${GIT_EXECUTABLE} pull WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/third-party/cpp-array OUTPUT_VARIABLE _revision) message(STATUS "Updating Cpp-Array") else() message(STATUS "Cloning Cpp-Array") execute_process( COMMAND ${GIT_EXECUTABLE} clone https://code.google.com/p/cpp-array.git ${PROJECT_SOURCE_DIR}/third-party/cpp-array OUTPUT_QUIET) endif() endif() if(EXISTS ${PROJECT_SOURCE_DIR}/third-party/cpp-array/) add_subdirectory(${PROJECT_SOURCE_DIR}/third-party/cpp-array/) set(CPP-ARRAY_TESTS OFF CACHE BOOL "cpparray tests" FORCE) mark_as_advanced(CPP-ARRAY_DEV) mark_as_advanced(CPP-ARRAY_DOCUMENTATION) mark_as_advanced(CPP-ARRAY_TESTS) mark_as_advanced(CUDA) mark_as_advanced(ARRAY_USER_LIB_PATH) list(APPEND AKANTU_EXTERNAL_LIB_INCLUDE_DIR ${cpp-array_INCLUDE_DIRS} ${CPP-ARRAY_INCLUDE_DIRS}) list(APPEND AKANTU_EXTERNAL_LIBRARIES ${CPP-ARRAY_LIBRARIES}) list(APPEND AKANTU_EXTERNAL_LIB_INCLUDE_DIR ${CPP-ARRAY_INCLUDE_DIRS}) list(APPEND CPACK_SOURCE_IGNORE_FILES ${PROJECT_SOURCE_DIR}/third-party/cpp-array/) set(AKANTU_CPPARRAY_INCLUDE_DIR ${cpp-array_INCLUDE_DIRS} ${CPP-ARRAY_INCLUDE_DIRS}) list(APPEND AKANTU_OPTION_LIST CPPARRAY) set(AKANTU_CPPARRAY ${AKANTU_CPPARRAY} CACHE INTERNAL "Use cpp-array library" FORCE) else() message(STATUS "Cpp-Array could not be found! Please install git and/or place cpp-array in the third-party folder of Akantu") endif() else() add_optional_external_package(CppArray "Use cpp-array library" OFF) endif() set(AKANTU_CPPARRAY_DOCUMENTATION " This package provides access to the \\href{https://code.google.com/p/cpp-array/}{cpp-array} open-source project. If internet is accessible when configuring the project (during cmake call) this package will be auto-downloaded. ") diff --git a/src/common/aka_voigthelper.cc b/src/common/aka_voigthelper.cc index deb4c24cb..2b075d673 100644 --- a/src/common/aka_voigthelper.cc +++ b/src/common/aka_voigthelper.cc @@ -1,125 +1,64 @@ /** * @file aka_voigthelper * * @author Lucas Frerot * * @date Thu 11 21 15:25:59 2013 * * @brief Voigt indices * * @section LICENSE * * Copyright (©) 2010-2013 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #include "aka_common.hh" #include "aka_voigthelper.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template <> const UInt VoigtHelper<1>::mat[][1] = {{0}}; template <> const UInt VoigtHelper<2>::mat[][2] = {{0, 2}, - {3, 1}}; + {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., 1., 2.}; template <> const Real VoigtHelper<3>::factors[] = {1., 1., 1., 2., 2., 2.}; -/* -------------------------------------------------------------------------- */ -template<> -void VoigtHelper<3>::transferBMatrixToBL2(const Matrix & B, const Matrix & grad_u, - Matrix & Bvoigt, - UInt nb_nodes_per_element) { - - Bvoigt.clear(); - - for (UInt i = 0; i < 3; ++i) - for (UInt j = 0; j < nb_nodes_per_element; ++j) - for (UInt k = 0; k < 3; ++k) - Bvoigt(i, j * 3 + k) = grad_u(k, i) * B(i, j); - - for (UInt i = 3; i < 6; ++i) - for (UInt j = 0; j < nb_nodes_per_element; ++j) - for (UInt k = 0; k < 3; ++k){ - UInt aux = i-3 ; - for (UInt m = 0; m < 3; ++m) { - if (m != aux) { - UInt index1 = m; - UInt index2 = 3 - m - aux; - Bvoigt(i, j * 3 + k) += grad_u(k, index1) * B(index2, j); - } - } - } -} - -/* -------------------------------------------------------------------------- */ -template<> -void VoigtHelper<2>::transferBMatrixToBL2(const Matrix & B, const Matrix & grad_u, - Matrix & Bvoigt, - UInt nb_nodes_per_element) { - - Bvoigt.clear(); - - for (UInt i = 0; i < 2; ++i) - for (UInt j = 0; j < nb_nodes_per_element; ++j) - for (UInt k = 0; k < 2; ++k) - Bvoigt(i, j * 2 + k) = grad_u(k, i) * B(i, j); - - for (UInt j = 0; j < nb_nodes_per_element; ++j) - for (UInt k = 0; k < 2; ++k) - for (UInt m = 0; m < 2; ++m) { - UInt index1 = m; - UInt index2 = (2 - 1) - m; - Bvoigt(2, j * 2 + k) += grad_u(k, index1) * B(index2, j); - } -} - -/* -------------------------------------------------------------------------- */ -template<> -void VoigtHelper<1>::transferBMatrixToBL2(const Matrix & B, const Matrix & grad_u, - Matrix & Bvoigt, - UInt nb_nodes_per_element) { - - Bvoigt.clear(); - - for (UInt j = 0; j < nb_nodes_per_element; ++j) - for (UInt k = 0; k < 2; ++k) - Bvoigt(0, j * 2 + k) = grad_u(k, 0) * B(0, j); -} __END_AKANTU__ diff --git a/src/common/aka_voigthelper.hh b/src/common/aka_voigthelper.hh index b3f271c8d..e8e8f2679 100644 --- a/src/common/aka_voigthelper.hh +++ b/src/common/aka_voigthelper.hh @@ -1,133 +1,200 @@ /** * @file aka_voigthelper * * @author Lucas Frerot * * @date Thu 11 21 13:48:26 2013 * * @brief Helper file for Voigt notation * * @section LICENSE * * Copyright (©) 2010-2013 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #ifndef __AKA_VOIGTHELPER_HH__ #define __AKA_VOIGTHELPER_HH__ #include "aka_common.hh" #include "aka_types.hh" __BEGIN_AKANTU__ + +/* -------------------------------------------------------------------------- */ template class VoigtHelper { - public: - /// transfer the B matrix to a Voigt notation B matrix - static void transferBMatrixToSymVoigtBMatrix(const Matrix & B, - Matrix & Bvoigt, - UInt nb_nodes_per_element); - - /// transfer the BNL matrix to a Voigt notation B matrix (See Bathe et al. IJNME vol 9, 1975) - static void transferBMatrixToBNL(const Matrix & B, - Matrix & Bvoigt, - UInt nb_nodes_per_element); - - /// transfer the BL2 matrix to a Voigt notation B matrix (See Bathe et al. IJNME vol 9, 1975) - static void transferBMatrixToBL2(const Matrix & B, const Matrix & grad_u, - Matrix & 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-(dim-1)/2)]; - +public: + /// transfer the B matrix to a Voigt notation B matrix + inline static void transferBMatrixToSymVoigtBMatrix(const Matrix & B, + Matrix & 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 & B, + Matrix & 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 & B, const Matrix & grad_u, + Matrix & 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-(dim-1)/2)]; }; template const UInt VoigtHelper::size = dim*(dim-(dim-1)/2); /* -------------------------------------------------------------------------- */ template -void VoigtHelper::transferBMatrixToSymVoigtBMatrix(const Matrix & B, - Matrix & Bvoigt, - UInt nb_nodes_per_element) { +inline void VoigtHelper::transferBMatrixToSymVoigtBMatrix(const Matrix & B, + Matrix & Bvoigt, + UInt nb_nodes_per_element) { Bvoigt.clear(); for (UInt i = 0; i < dim; ++i) for (UInt n = 0; n < nb_nodes_per_element; ++n) Bvoigt(i, i + n*dim) = B(i, n); if(dim == 2) { ///in 2D, fill the @f$ [\frac{\partial N_i}{\partial x}, \frac{\partial N_i}{\partial y}]@f$ row for (UInt n = 0; n < nb_nodes_per_element; ++n) { Bvoigt(2, 1 + n*2) = B(0, n); Bvoigt(2, 0 + n*2) = B(1, n); } } if(dim == 3) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { Real dndx = B(0, n); Real dndy = B(1, n); Real dndz = B(2, n); ///in 3D, fill the @f$ [0, \frac{\partial N_i}{\partial y}, \frac{N_i}{\partial z}]@f$ row Bvoigt(3, 1 + n*3) = dndz; Bvoigt(3, 2 + n*3) = dndy; ///in 3D, fill the @f$ [\frac{\partial N_i}{\partial x}, 0, \frac{N_i}{\partial z}]@f$ row Bvoigt(4, 0 + n*3) = dndz; Bvoigt(4, 2 + n*3) = dndx; ///in 3D, fill the @f$ [\frac{\partial N_i}{\partial x}, \frac{N_i}{\partial y}, 0]@f$ row Bvoigt(5, 0 + n*3) = dndy; Bvoigt(5, 1 + n*3) = dndx; } } } /* -------------------------------------------------------------------------- */ template -void VoigtHelper::transferBMatrixToBNL(const Matrix & B, - Matrix & Bvoigt, - UInt nb_nodes_per_element) { +inline void VoigtHelper::transferBMatrixToBNL(const Matrix & B, + Matrix & Bvoigt, + UInt nb_nodes_per_element) { + Bvoigt.clear(); + + //see Finite element formulations for large deformation dynamic analysis, + //Bathe et al. IJNME vol 9, 1975, page 364 B_{NL} + for (UInt i = 0; i < dim; ++i) { + for (UInt m = 0; m < nb_nodes_per_element; ++m) { + for (UInt n = 0; n < dim; ++n) { + //std::cout << B(n, m) << std::endl; + Bvoigt(i * dim + n, m * dim + i) = B(n, m); + } + } + } + //TODO: Verify the 2D and 1D case +} - Bvoigt.clear(); - //see Finite element formulations for large deformation dynamic analysis, Bathe et al. IJNME vol 9, 1975, page 364 B_{NL} +/* -------------------------------------------------------------------------- */ +template<> +inline void VoigtHelper<1>::transferBMatrixToBL2(const Matrix & B, + const Matrix & grad_u, + Matrix & Bvoigt, + UInt nb_nodes_per_element) { + Bvoigt.clear(); + for (UInt j = 0; j < nb_nodes_per_element; ++j) + for (UInt k = 0; k < 2; ++k) + Bvoigt(0, j * 2 + k) = grad_u(k, 0) * B(0, j); +} - for (UInt i = 0; i < dim; ++i) { - for (UInt m = 0; m < nb_nodes_per_element; ++m) { - for (UInt n = 0; n < dim; ++n) { - //std::cout << B(n, m) << std::endl; - Bvoigt(i * dim + n, m * dim + i) = B(n, m); - } +/* -------------------------------------------------------------------------- */ +template<> +inline void VoigtHelper<3>::transferBMatrixToBL2(const Matrix & B, + const Matrix & grad_u, + Matrix & Bvoigt, + UInt nb_nodes_per_element) { + Bvoigt.clear(); + + for (UInt i = 0; i < 3; ++i) + for (UInt j = 0; j < nb_nodes_per_element; ++j) + for (UInt k = 0; k < 3; ++k) + Bvoigt(i, j * 3 + k) = grad_u(k, i) * B(i, j); + + for (UInt i = 3; i < 6; ++i) { + for (UInt j = 0; j < nb_nodes_per_element; ++j) { + for (UInt k = 0; k < 3; ++k){ + UInt aux = i-3; + for (UInt m = 0; m < 3; ++m) { + if (m != aux) { + UInt index1 = m; + UInt index2 = 3 - m - aux; + Bvoigt(i, j * 3 + k) += grad_u(k, index1) * B(index2, j); + } } + } } - //TODO: Verify the 2D and 1D case + } +} + +/* -------------------------------------------------------------------------- */ +template<> +inline void VoigtHelper<2>::transferBMatrixToBL2(const Matrix & B, + const Matrix & grad_u, + Matrix & Bvoigt, + UInt nb_nodes_per_element) { + + Bvoigt.clear(); + + for (UInt i = 0; i < 2; ++i) + for (UInt j = 0; j < nb_nodes_per_element; ++j) + for (UInt k = 0; k < 2; ++k) + Bvoigt(i, j * 2 + k) = grad_u(k, i) * B(i, j); + + for (UInt j = 0; j < nb_nodes_per_element; ++j) { + for (UInt k = 0; k < 2; ++k) { + for (UInt m = 0; m < 2; ++m) { + UInt index1 = m; + UInt index2 = (2 - 1) - m; + Bvoigt(2, j * 2 + k) += grad_u(k, index1) * B(index2, j); + } + } + } } __END_AKANTU__ #endif diff --git a/src/io/dumper/dumper_material_padders.hh b/src/io/dumper/dumper_material_padders.hh index 89de5a80c..a541cbb56 100644 --- a/src/io/dumper/dumper_material_padders.hh +++ b/src/io/dumper/dumper_material_padders.hh @@ -1,136 +1,135 @@ - #ifndef __AKANTU_DUMPER_MATERIAL_PADDERS_HH__ #define __AKANTU_DUMPER_MATERIAL_PADDERS_HH__ /* -------------------------------------------------------------------------- */ #include "dumper_padding_helper.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ __BEGIN_AKANTU_DUMPER__ /* -------------------------------------------------------------------------- */ template class MaterialPadder : public PadderGeneric, R > { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - MaterialPadder(const SolidMechanicsModel & model) : + MaterialPadder(const SolidMechanicsModel & model) : model(model), element_index_by_material(model.getElementIndexByMaterial()) { } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ /// return the material from the global element index const Material & getMaterialFromGlobalIndex(Element global_index){ UInt index = global_index.getIndex(); UInt material_id = element_index_by_material(global_index.getType())(index); const Material & material = model.getMaterial(material_id); return material; } /// return the type of the element from global index const 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 & element_index_by_material; /// the number of data per element const ElementTypeMapArray nb_data_per_element; }; /* -------------------------------------------------------------------------- */ template -class StressPadder : +class StressPadder : public MaterialPadder > { public: StressPadder(const SolidMechanicsModel & model) : MaterialPadder >(model){ this->setPadding(3,3); } inline Matrix func(const Vector & in, Element global_element_id){ - UInt nrows = spatial_dimension; + UInt nrows = spatial_dimension; UInt ncols = in.size() / nrows; - UInt nb_data = in.size() / ncols; + UInt nb_data = in.size() / (ncols*ncols); Matrix stress = this->pad(in, nrows,ncols, nb_data); const Material & material = this->getMaterialFromGlobalIndex(global_element_id); bool plane_strain = !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(UInt old_nb_comp){ return this->getDim(); }; }; /* -------------------------------------------------------------------------- */ template class StrainPadder : public MaterialPadder > { public: - StrainPadder(const SolidMechanicsModel & model) : + StrainPadder(const SolidMechanicsModel & model) : MaterialPadder >(model) { this->setPadding(3,3); } inline Matrix func(const Vector & in, Element global_element_id){ - UInt nrows = spatial_dimension; + UInt nrows = spatial_dimension; UInt ncols = in.size() / nrows; UInt nb_data = in.size() / ncols; Matrix strain = this->pad(in, nrows,ncols, 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(UInt old_nb_comp){ return this->getDim(); }; }; /* -------------------------------------------------------------------------- */ __END_AKANTU_DUMPER__ __END_AKANTU__ #endif /* __AKANTU_DUMPER_MATERIAL_PADDERS_HH__ */ diff --git a/src/io/mesh_io/mesh_io_abaqus.cc b/src/io/mesh_io/mesh_io_abaqus.cc index 8a8bf13f5..8b06be5a1 100644 --- a/src/io/mesh_io/mesh_io_abaqus.cc +++ b/src/io/mesh_io/mesh_io_abaqus.cc @@ -1,535 +1,539 @@ /** * @file mesh_io_abaqus.cc * @author Alejandro M. Aragón * @author Nicolas Richart * @date Fri Oct 7 10:58:00 2011 * * @brief read a mesh from an abaqus input file * * @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 . * */ /* -------------------------------------------------------------------------- */ // std library header files #include // akantu header files #include "mesh_io_abaqus.hh" #include "mesh.hh" #include "element_group.hh" #include "node_group.hh" /* -------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include /* -------------------------------------------------------------------------- */ __BEGIN_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; namespace mesh_io_abaqus_lazy_eval { struct mesh_abaqus_error_handler_ { template struct result { typedef void type; }; template void operator()(qi::info const& what, Iterator err_pos, Iterator last) const { AKANTU_EXCEPTION("Error! Expecting " << what // what failed? << " here: \"" << std::string(err_pos, last) // iterators to error-pos, end << "\""); } }; struct lazy_element_read_ { template struct result { typedef void type; }; template void operator()(Mesh & mesh, const ET & type, const ID & id, const V & conn, const NodeMap & nodes_mapping, ElemMap & elements_mapping) const { Vector 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 & connectivity = mesh.getConnectivity(type); UInt i = 0; for(typename V::const_iterator it = conn.begin(); it != conn.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; } Element el(type, connectivity.getSize()); elements_mapping[id] = el; connectivity.push_back(tmp_conn); } }; struct lazy_node_read_ { template struct result { typedef void type; }; template void operator()(Mesh & mesh, const ID & id, const V & pos, Map & nodes_mapping) const { Vector 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); } }; /* ------------------------------------------------------------------------ */ struct lazy_element_group_create_ { template struct result { typedef ElementGroup & type; }; template ElementGroup & operator()(Mesh & mesh, const S & name) const { typename 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); } } }; struct lazy_add_element_to_group_ { template struct result { typedef void type; }; template void operator()(EG * el_grp, const ID & element, const Map & elements_mapping) const { typename Map::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); } }; /* ------------------------------------------------------------------------ */ struct lazy_node_group_create_ { template struct result { typedef NodeGroup & type; }; template NodeGroup & operator()(Mesh & mesh, const S & name) const { typename 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()); } } }; struct lazy_add_node_to_group_ { template struct result { typedef void type; }; template void operator()(NG * node_grp, const ID & node, const Map & nodes_mapping) const { typename Map::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); } }; struct lazy_optimize_group_ { template struct result { typedef void type; }; template void operator()(G * grp) const { grp->optimize(); } }; } /* -------------------------------------------------------------------------- */ template struct AbaqusSkipper : qi::grammar { AbaqusSkipper() : AbaqusSkipper::base_type(skip, "abaqus_skipper") { skip = (ascii::space - spirit::eol) | "**" >> *(qi::char_ - spirit::eol) >> spirit::eol ; } qi::rule skip; }; /* -------------------------------------------------------------------------- */ template > struct AbaqusMeshGrammar : qi::grammar { public: AbaqusMeshGrammar(Mesh & mesh) : AbaqusMeshGrammar::base_type(start, "abaqus_mesh_reader"), mesh(mesh) { phx::function const error_handler = mesh_io_abaqus_lazy_eval::mesh_abaqus_error_handler_(); phx::function lazy_element_read; phx::function lazy_node_read; phx::function lazy_element_group_create; phx::function lazy_add_element_to_group; phx::function lazy_node_group_create; phx::function lazy_add_node_to_group; phx::function lazy_optimize_group; start - = *(qi::char_('*') - > ( (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) - ) - ) + = *( + (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) [ lazy_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) [ lazy_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") ] >> '=' + ( qi::char_(',') >> qi::no_case[ qi::lit("elset") ] >> '=' >> value [ lbs::_a = &lazy_element_group_create(phx::ref(mesh), lbs::_1) ] ) ^ *(qi::char_(',') >> option) ) >> spirit::eol >> qi::skip (qi::char_(',') | qi::space) [ +(qi::int_ [ lazy_add_element_to_group(lbs::_a, lbs::_1, phx::cref(abaqus_elements_to_akantu) ) ] ) ] ) [ lazy_optimize_group(lbs::_a) ] ; nodes_set = ( ( ( qi::char_(',') >> qi::no_case[ qi::lit("nset") ] >> '=' >> value [ lbs::_a = &lazy_node_group_create(phx::ref(mesh), lbs::_1) ] ) ^ *(qi::char_(',') >> option) ) >> spirit::eol >> qi::skip (qi::char_(',') | qi::space) [ +(qi::int_ [ lazy_add_node_to_group(lbs::_a, lbs::_1, phx::cref(abaqus_nodes_to_akantu) ) ] ) ] ) [ lazy_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::char_ - (qi::char_('*') | spirit::eol)) + = qi::lexeme[ +(qi::char_ - (qi::char_('*') | spirit::eol)) ] ; option - = key >> '=' >> value; + = key > -( '=' >> value ); key - = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9") + = 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); qi::on_error(start, error_handler(lbs::_4, lbs::_3, lbs::_2)); - start .name("abaqus-start-rule"); + 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"); } public: AKANTU_GET_MACRO(MaterialNames, material_names, const std::vector &); /* ------------------------------------------------------------------------ */ /* Rules */ /* ------------------------------------------------------------------------ */ private: qi::rule start; qi::rule(), Skipper> connectivity; qi::rule(), Skipper> node_position; qi::rule nodes, any_section, header, material; qi::rule, Skipper> elements; qi::rule, Skipper> elements_set; qi::rule, Skipper> nodes_set; qi::rule key, value, option, keyword, any_line; qi::real_parser< Real, qi::real_policies > real; qi::symbols 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 abaqus_nodes_to_akantu; /// correspondance between the element number in the abaqus file and the /// Element in the akantu mesh std::map abaqus_elements_to_akantu; /// list of the material names std::vector 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(infile), std::istream_iterator(), std::back_inserter(storage)); typedef std::string::const_iterator iterator_t; typedef AbaqusSkipper skipper; typedef AbaqusMeshGrammar 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::const_iterator mnit = g.getMaterialNames().begin(); std::vector::const_iterator mnend = g.getMaterialNames().end(); 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 & abaqus_material = *mesh.getDataPointer("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; } } } } } __END_AKANTU__ diff --git a/src/io/parser/cppargparse/cppargparse_tmpl.hh b/src/io/parser/cppargparse/cppargparse_tmpl.hh index ec4f77c32..adcafd9e5 100644 --- a/src/io/parser/cppargparse/cppargparse_tmpl.hh +++ b/src/io/parser/cppargparse/cppargparse_tmpl.hh @@ -1,255 +1,260 @@ /** * @file cppargparse_tmpl.hh * * @author Nicolas Richart * * @date Mon Mar 31 21:15:31 2014 * * @brief * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include #ifndef __CPPARGPARSE_TMPL_HH__ #define __CPPARGPARSE_TMPL_HH__ namespace cppargparse { /* -------------------------------------------------------------------------- */ /* Argument */ /* -------------------------------------------------------------------------- */ struct ArgumentParser::_Argument : public Argument { _Argument() : Argument(), help(std::string()), nargs(1), type(_string), required(false), parsed(false), has_default(false), has_const(false), is_positional(false) {} virtual ~_Argument() {} void setValues(std::vector & values) { for (std::vector::iterator it = values.begin(); it != values.end(); ++it) { this->addValue(*it); } } virtual void addValue(std::string & value) = 0; virtual void setToDefault() = 0; virtual void setToConst() = 0; std::ostream & printDefault(std::ostream & stream) const { stream << std::boolalpha; if(has_default) { stream << " (default: "; this->_printDefault(stream); stream << ")"; } if(has_const) { stream << " (const: "; this->_printConst(stream); stream << ")"; } return stream; } virtual std::ostream & _printDefault(std::ostream & stream) const = 0; virtual std::ostream & _printConst(std::ostream & stream) const = 0; std::string help; int nargs; ArgumentType type; bool required; bool parsed; bool has_default; bool has_const; std::vector keys; bool is_positional; }; /* -------------------------------------------------------------------------- */ template class ArgumentParser::ArgumentStorage : public ArgumentParser::_Argument { public: ArgumentStorage() : _default(T()), _const(T()), values(std::vector()) {} virtual void addValue(std::string & value) { std::stringstream sstr(value); T t; sstr >> t; values.push_back(t); } virtual void setToDefault() { values.clear(); values.push_back(_default); } virtual void setToConst() { values.clear(); values.push_back(_const); } void printself(std::ostream & stream) const { stream << this->name << " ="; stream << std::boolalpha; // for boolean for(typename std::vector::const_iterator vit = this->values.begin(); vit != this->values.end(); ++vit) { stream << " " << *vit; } } virtual std::ostream & _printDefault(std::ostream & stream) const { stream << _default; return stream; } virtual std::ostream & _printConst(std::ostream & stream) const { stream << _const; return stream; } T _default; T _const; std::vector values; }; /* -------------------------------------------------------------------------- */ template<> inline void ArgumentParser::ArgumentStorage::addValue(std::string & value) { values.push_back(value); } template struct is_vector { enum { value = false }; }; template struct is_vector< std::vector > { enum { value = true }; }; /* -------------------------------------------------------------------------- */ template::value> struct cast_helper { static T cast(const ArgumentParser::Argument & arg) { const ArgumentParser::ArgumentStorage & _arg = dynamic_cast &>(arg); if(_arg.values.size() == 1) { return _arg.values[0]; } else { throw std::length_error("Not enougth or too many argument where passed for the command line argument: " + arg.name); } } }; template struct cast_helper { static T cast(const ArgumentParser::Argument & arg) { const ArgumentParser::ArgumentStorage & _arg = dynamic_cast &>(arg); return _arg.values; } }; /* -------------------------------------------------------------------------- */ template ArgumentParser::Argument::operator T() const{ return cast_helper::cast(*this); } +template<> +inline ArgumentParser::Argument::operator unsigned int() const{ + return cast_helper::cast(*this); +} + template void ArgumentParser::addArgument(const std::string & name_or_flag, const std::string & help, int nargs, ArgumentType type, T def) { _Argument & arg = _addArgument(name_or_flag, help, nargs, type); dynamic_cast &>(arg)._default = def; arg.has_default = true; } template void ArgumentParser::addArgument(const std::string & name_or_flag, const std::string & help, int nargs, ArgumentType type, T def, T cons) { _Argument & arg = _addArgument(name_or_flag, help, nargs, type); dynamic_cast &>(arg)._default = def; arg.has_default = true; dynamic_cast &>(arg)._const = cons; arg.has_const = true; } /* -------------------------------------------------------------------------- */ template<> inline void ArgumentParser::addArgument(const std::string & name_or_flag, const std::string & help, int nargs, ArgumentType type, const char * def) { this->addArgument(name_or_flag, help, nargs, type, def); } template<> inline void ArgumentParser::addArgument(const std::string & name_or_flag, const std::string & help, int nargs, ArgumentType type, unsigned int def) { this->addArgument(name_or_flag, help, nargs, type, def); } /* -------------------------------------------------------------------------- */ template<> inline void ArgumentParser::addArgument(const std::string & name_or_flag, const std::string & help, int nargs, ArgumentType type, const char * def, const char * cons) { this->addArgument(name_or_flag, help, nargs, type, def, cons); } template<> inline void ArgumentParser::addArgument(const std::string & name_or_flag, const std::string & help, int nargs, ArgumentType type, unsigned int def, unsigned int cons) { this->addArgument(name_or_flag, help, nargs, type, def, cons); } } #endif /* __AKANTU_CPPARGPARSE_TMPL_HH__ */ diff --git a/src/model/boundary_condition_functor.hh b/src/model/boundary_condition_functor.hh index ecec08b70..76fc61080 100644 --- a/src/model/boundary_condition_functor.hh +++ b/src/model/boundary_condition_functor.hh @@ -1,206 +1,202 @@ /** * @file boundary_condition_functor.hh * * @author Dana Christen * * @date Wed Mar 18 11:30:00 2013 * * @brief XXX * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_BOUNDARY_CONDITION_FUNCTOR_HH__ #define __AKANTU_BOUNDARY_CONDITION_FUNCTOR_HH__ #include "aka_common.hh" #include "fe_engine.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ namespace BC { - enum Axis { - _x = 0, - _y = 1, - _z = 2, - }; + typedef ::akantu::SpacialDirection Axis; struct Functor { enum Type { _dirichlet, _neumann }; }; /* ------------------------------------------------------------------------ */ /* Dirichlet */ /* ------------------------------------------------------------------------ */ namespace Dirichlet { /* ---------------------------------------------------------------------- */ class DirichletFunctor : public Functor { protected: DirichletFunctor() : axis(_x) {} DirichletFunctor(Axis ax) : axis(ax) {} public: void operator()(UInt node, Vector & flags, Vector & primal, const Vector & coord) const { AKANTU_DEBUG_TO_IMPLEMENT(); } public: static const Type type = _dirichlet; protected: Axis axis; }; /* ---------------------------------------------------------------------- */ class FlagOnly : public DirichletFunctor { public: FlagOnly(Axis ax = _x) : DirichletFunctor(ax) {} public: inline void operator()(UInt node, Vector & flags, Vector & primal, const Vector & coord) const; }; /* ---------------------------------------------------------------------- */ class FreeBoundary : public DirichletFunctor { public: FreeBoundary(Axis ax = _x) : DirichletFunctor(ax) {} public: inline void operator()(UInt node, Vector & flags, Vector & primal, const Vector & coord) const; }; /* ---------------------------------------------------------------------- */ class FixedValue : public DirichletFunctor { public: FixedValue(Real val, Axis ax = _x) : DirichletFunctor(ax), value(val) {} public: inline void operator()(UInt node, Vector & flags, Vector & primal, const Vector & 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 & flags, Vector & primal, const Vector & 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: void operator()(UInt node, Vector & flags, Vector & primal, const Vector & coord) const { AKANTU_DEBUG_TO_IMPLEMENT(); } public: static const Type type = _neumann; }; /* ---------------------------------------------------------------------- */ class FromHigherDim : public NeumannFunctor { public: FromHigherDim(const Matrix & mat) : bc_data(mat) {} public: inline void operator()(const QuadraturePoint & quad_point, Vector & dual, const Vector & coord, const Vector & normals) const; protected: Matrix bc_data; }; /* ---------------------------------------------------------------------- */ class FromSameDim : public NeumannFunctor { public: FromSameDim(const Vector & vec) : bc_data(vec) {} public: inline void operator()(const QuadraturePoint & quad_point, Vector & dual, const Vector & coord, const Vector & normals) const; protected: Vector bc_data; }; /* ---------------------------------------------------------------------- */ class FreeBoundary : public NeumannFunctor { public: inline void operator()(const QuadraturePoint & quad_point, Vector & dual, const Vector & coord, const Vector & normals) const; }; } //end namespace Neumann } //end namespace BC __END_AKANTU__ #include "boundary_condition_functor_inline_impl.cc" #endif /* __AKANTU_BOUNDARY_CONDITION_FUNCTOR_HH__ */ diff --git a/src/model/solid_mechanics/material_list.hh b/src/model/solid_mechanics/material_list.hh index 60531b7fe..9e2154a15 100644 --- a/src/model/solid_mechanics/material_list.hh +++ b/src/model/solid_mechanics/material_list.hh @@ -1,98 +1,102 @@ /** * @file material_list.hh * * @author Nicolas Richart * * @date Tue Oct 29 10:08:25 2013 * * @brief List of materials and all includes * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_LIST_HH__ #define __AKANTU_MATERIAL_LIST_HH__ #include "aka_config.hh" /* -------------------------------------------------------------------------- */ /* Material list */ /* -------------------------------------------------------------------------- */ #ifndef AKANTU_CMAKE_LIST_MATERIALS // elastic materials #include "material_elastic.hh" #include "material_neohookean.hh" +#include "material_elastic_orthotropic.hh" +#include "material_elastic_linear_anisotropic.hh" // visco-elastic materials #include "material_standard_linear_solid_deviatoric.hh" // damage laws #include "material_marigo.hh" #include "material_mazars.hh" // small-deformation plasticity #include "material_linear_isotropic_hardening.hh" #endif #define AKANTU_CORE_MATERIAL_LIST \ ((2, (elastic , MaterialElastic ))) \ ((2, (neohookean , MaterialNeohookean ))) \ + ((2, (elastic_orthotropic, MaterialElasticOrthotropic ))) \ + ((2, (elastic_anisotropic, MaterialElasticLinearAnisotropic ))) \ ((2, (sls_deviatoric , MaterialStandardLinearSolidDeviatoric))) \ ((2, (marigo , MaterialMarigo ))) \ ((2, (mazars , MaterialMazars ))) \ ((2, (plastic_linear_isotropic_hardening, MaterialLinearIsotropicHardening))) #if defined(AKANTU_EXTRA_MATERIALS) # include "material_extra_includes.hh" #else # define AKANTU_EXTRA_MATERIAL_LIST #endif #if defined(AKANTU_COHESIVE_ELEMENT) # include "material_cohesive_includes.hh" #else # define AKANTU_COHESIVE_MATERIAL_LIST #endif #if defined(AKANTU_DAMAGE_NON_LOCAL) # include "material_non_local_includes.hh" #else # define AKANTU_DAMAGE_NON_LOCAL_MATERIAL_LIST #endif #if defined(AKANTU_DAMAGE_NON_LOCAL_EXTRA) # include "material_non_local_extra_includes.hh" #else # define AKANTU_DAMAGE_NON_LOCAL_EXTRA_MATERIAL_LIST #endif #define AKANTU_MATERIAL_LIST \ AKANTU_CORE_MATERIAL_LIST \ AKANTU_EXTRA_MATERIAL_LIST \ AKANTU_COHESIVE_MATERIAL_LIST \ AKANTU_DAMAGE_NON_LOCAL_MATERIAL_LIST \ AKANTU_DAMAGE_NON_LOCAL_EXTRA_MATERIAL_LIST #endif /* __AKANTU_MATERIAL_LIST_HH__ */ 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 c1a06a33a..7d0e0040e 100644 --- a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc +++ b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc @@ -1,334 +1,329 @@ /** * @file material_elastic_linear_anisotropic.cc * * @author Till Junge * * @date Tue May 08 13:01:18 2012 * * @brief Anisotropic elastic material * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "material_elastic_linear_anisotropic.hh" #include "solid_mechanics_model.hh" #include #include __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template MaterialElasticLinearAnisotropic:: MaterialElasticLinearAnisotropic(SolidMechanicsModel & model, const ID & id, bool symmetric) : Material(model, id), rot_mat(spatial_dimension, spatial_dimension), Cprime(spatial_dimension*spatial_dimension, spatial_dimension*spatial_dimension), C(this->voigt_h.size, this->voigt_h.size), eigC(this->voigt_h.size), symmetric(symmetric), - alpha(0){ + alpha(0) { AKANTU_DEBUG_IN(); this->dir_vecs.push_back(new Vector(spatial_dimension)); (*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(spatial_dimension)); (*this->dir_vecs.back())[1] = 1.; this->registerParam("n2", *(this->dir_vecs.back()), _pat_parsmod, "Direction of secondary material axis"); if (spatial_dimension > 2) { this->dir_vecs.push_back(new Vector(spatial_dimension)); (*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 < this->voigt_h.size ; ++i) { UInt start = 0; if (this->symmetric) { start = i; } for (UInt j = start ; j < this->voigt_h.size ; ++j) { std::stringstream param("C"); param << "C" << i+1 << j+1; this->registerParam(param.str() , this->Cprime(i,j), 0., _pat_parsmod, "Coefficient " + param.str()); } } this->registerParam("alpha", this->alpha, _pat_parsmod, "Proportion of viscous stress"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template MaterialElasticLinearAnisotropic::~MaterialElasticLinearAnisotropic() { for (UInt i = 0 ; i < spatial_dimension ; ++i) { delete this->dir_vecs[i]; } } /* -------------------------------------------------------------------------- */ template void MaterialElasticLinearAnisotropic::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); updateInternalParameters(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialElasticLinearAnisotropic::updateInternalParameters() { Material::updateInternalParameters(); if (this->symmetric) { for (UInt i = 0 ; i < this->voigt_h.size ; ++i) { for (UInt j = i+1 ; j < this->voigt_h.size ; ++j) { this->Cprime(j, i) = this->Cprime(i, j); } } } this->rotateCprime(); this->C.eig(this->eigC); } /* -------------------------------------------------------------------------- */ template void MaterialElasticLinearAnisotropic::rotateCprime() { // start by filling the empty parts fo Cprime UInt diff = Dim*Dim - this->voigt_h.size; for (UInt i = this->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 = this->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 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 test_axis(3); Vector 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::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 rotator(Dim * Dim, Dim * Dim); Matrix 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 = this->voigt_h.mat[i][j]; UInt J = this->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 Cfull(Dim*Dim, Dim*Dim); Cfull = rotator*Cprime*revrotor; for (UInt i = 0 ; i < this->voigt_h.size ; ++i) { for (UInt j = 0 ; j < this->voigt_h.size ; ++j) { this->C(i, j) = Cfull(i, j); } } } /* -------------------------------------------------------------------------- */ template -void MaterialElasticLinearAnisotropic:: -computeStress(ElementType el_type, GhostType ghost_type) { - if (this->alpha == 0.) { - this->computeStressWorker(el_type, ghost_type); - } else { - this->computeStressWorker(el_type, ghost_type); - } -} - - -/* -------------------------------------------------------------------------- */ -template -template -void MaterialElasticLinearAnisotropic:: -computeStressWorker(ElementType el_type, GhostType ghost_type) { - +void MaterialElasticLinearAnisotropic::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::iterator< Matrix > gradu_it = this->gradu(el_type, ghost_type).begin(spatial_dimension, - spatial_dimension); + spatial_dimension); Array::iterator< Matrix > gradu_end = this->gradu(el_type, ghost_type).end(spatial_dimension, - spatial_dimension); - - Array strain_rate(0, spatial_dimension * spatial_dimension, - "strain_rate"); - Array::iterator< Matrix > strain_rate_it; - if (viscous) { - const Array & elem_filter = this->element_filter(el_type, ghost_type); - Array & velocity = this->model->getVelocity(); - this->model->getFEEngine().gradientOnQuadraturePoints(velocity, strain_rate, - spatial_dimension, el_type, - ghost_type, - elem_filter); - strain_rate_it = strain_rate.begin(spatial_dimension, spatial_dimension); - } - this->stress(el_type, ghost_type).resize(this->gradu(el_type, - ghost_type).getSize()); + spatial_dimension); 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 voigt_strains(this->voigt_h.size, nb_quad_pts); Matrix voigt_stresses(this->voigt_h.size, nb_quad_pts); - Matrix * grad_u_dot; + // copy strains + Matrix strain(spatial_dimension, spatial_dimension); + for (UInt q = 0; gradu_it != gradu_end ; ++gradu_it, ++q) { Matrix & grad_u = *gradu_it; - if (viscous) { - grad_u_dot = &(*strain_rate_it); + + for(UInt I = 0; I < this->voigt_h.size; ++I) { + Real voigt_factor = this->voigt_h.factors[I]; + UInt i = this->voigt_h.vec[I][0]; + UInt j = this->voigt_h.vec[I][1]; + + voigt_strains(I, q) = voigt_factor * (grad_u(i, j) + grad_u(j, i)) / 2.; } - for (UInt i = 0 ; i < spatial_dimension ; ++i) { - for (UInt j = i ; j < spatial_dimension ; ++j) { - UInt I = this->voigt_h.mat[i][j]; - voigt_strains(I, q) = 0.5 * this->voigt_h.factors[I]*(grad_u(j,i) - + grad_u(i,j)); - if (viscous) { - voigt_strains(I, q) += (0.5 * this->alpha * this->voigt_h.factors[I] * - (grad_u_dot->operator()(j, i) - + grad_u_dot->operator()(i, j))); - } + } + + + // compute the strain rate proportional part if needed + bool viscous = this->alpha == 0.; // only works id default value + if(viscous) { + Array strain_rate(0, spatial_dimension * spatial_dimension, + "strain_rate"); + + Array & velocity = this->model->getVelocity(); + const Array & elem_filter = this->element_filter(el_type, ghost_type); + + this->model->getFEEngine().gradientOnQuadraturePoints(velocity, strain_rate, + spatial_dimension, el_type, + ghost_type, elem_filter); + + Array::matrix_iterator gradu_dot_it = strain_rate.begin(spatial_dimension, + spatial_dimension); + Array::matrix_iterator gradu_dot_end = strain_rate.end(spatial_dimension, + spatial_dimension); + + Matrix strain_dot(spatial_dimension, spatial_dimension); + for (UInt q = 0; gradu_dot_it != gradu_dot_end ; ++gradu_dot_it, ++q) { + Matrix & grad_u_dot = *gradu_dot_it; + + for(UInt I = 0; I < this->voigt_h.size; ++I) { + Real voigt_factor = this->voigt_h.factors[I]; + UInt i = this->voigt_h.vec[I][0]; + UInt j = this->voigt_h.vec[I][1]; + + voigt_strains(I, q) = this->alpha * voigt_factor * (grad_u_dot(i, j) + grad_u_dot(j, i)) / 2.; } } - if (viscous) { - ++strain_rate_it; - } } // compute stresses voigt_stresses = this->C * voigt_strains; // copy stresses back Array::iterator< Matrix > stress_it = this->stress(el_type, ghost_type).begin(spatial_dimension, - spatial_dimension); + spatial_dimension); + Array::iterator< Matrix > stress_end = this->stress(el_type, ghost_type).end(spatial_dimension, - spatial_dimension); + spatial_dimension); + for (UInt q = 0 ; stress_it != stress_end; ++stress_it, ++q) { Matrix & stress = *stress_it; - for (UInt i = 0 ; i < spatial_dimension ; ++i) { - stress(i,i) = voigt_stresses(this->voigt_h.mat[i][i], q); - for (UInt j = i+1 ; j < spatial_dimension ; ++j) { - UInt I = this->voigt_h.mat[i][j]; - stress(j, i) = - stress(i, j) = voigt_stresses(I, q); - } + + for(UInt I = 0; I < this->voigt_h.size; ++I) { + UInt i = this->voigt_h.vec[I][0]; + UInt j = this->voigt_h.vec[I][1]; + stress(i, j) = stress(j, i) = voigt_stresses(I, q); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialElasticLinearAnisotropic::computeTangentModuli(const ElementType & el_type, Array & 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; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template Real MaterialElasticLinearAnisotropic::getCelerity(__attribute__((unused)) const Element & element) const { return std::sqrt( this->eigC(0) / rho); } /* -------------------------------------------------------------------------- */ INSTANSIATE_MATERIAL(MaterialElasticLinearAnisotropic); __END_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 87e8ee53d..e2fb22798 100644 --- a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh +++ b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh @@ -1,121 +1,119 @@ /** * @file material_elastic_orthotropic.hh * * @author Till Junge * * @date Tue May 08 13:01:18 2012 * * @brief Orthotropic elastic material * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" #include "material_elastic.hh" #include /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_ELASTIC_LINEAR_ANISOTROPIC_HH__ #define __AKANTU_MATERIAL_ELASTIC_LINEAR_ANISOTROPIC_HH__ __BEGIN_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 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 & tangent_matrix, GhostType ghost_type = _not_ghost); virtual void updateInternalParameters(); protected: // compute C from Cprime void rotateCprime(); - //worker function computing stress - template - inline void computeStressWorker(ElementType el_type, - GhostType ghost_type = _not_ghost); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// compute max wave celerity virtual Real getCelerity(const Element & element) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: const static VoigtHelper voigt_h; /// direction matrix and vectors std::vector*> dir_vecs; + Matrix rot_mat; /// Elastic stiffness tensor in material frame and full vectorised notation Matrix Cprime; /// Elastic stiffness tensor in voigt notation Matrix C; /// eigenvalues of stiffness tensor Vector eigC; bool symmetric; + /// viscous proportion Real alpha; }; __END_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 b4add4dab..6c03d5bf2 100644 --- a/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc +++ b/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc @@ -1,211 +1,208 @@ /** * @file material_elastic_orthotropic.cc * * @author Till Jugne * @author Marco Vocialta * * @date Tue May 08 13:01:18 2012 * * @brief Orthotropic elastic material * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "material_elastic_orthotropic.hh" #include "solid_mechanics_model.hh" #include __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template MaterialElasticOrthotropic::MaterialElasticOrthotropic(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialElasticLinearAnisotropic(model, id) { AKANTU_DEBUG_IN(); this->registerParam("E1", E1 , 0., _pat_parsmod, "Young's modulus (n1)"); this->registerParam("E2", E2 , 0., _pat_parsmod, "Young's modulus (n2)"); this->registerParam("nu12", nu12, 0., _pat_parsmod, "Poisson's ratio (12)"); this->registerParam("G12", G12 , 0., _pat_parsmod, "Shear modulus (12)"); if (Dim > 2) { this->registerParam("E3" , E3 , 0., _pat_parsmod, "Young's modulus (n3)"); this->registerParam("nu13", nu13, 0., _pat_parsmod, "Poisson's ratio (13)"); this->registerParam("nu23", nu23, 0., _pat_parsmod, "Poisson's ratio (23)"); this->registerParam("G13" , G13 , 0., _pat_parsmod, "Shear modulus (13)"); this->registerParam("G23" , G23 , 0., _pat_parsmod, "Shear modulus (23)"); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template MaterialElasticOrthotropic::~MaterialElasticOrthotropic() { } /* -------------------------------------------------------------------------- */ template void MaterialElasticOrthotropic::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); updateInternalParameters(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline Real vector_norm(Vector & vec) { Real norm = 0; for (UInt i = 0 ; i < vec.size() ; ++i) { norm += vec(i)*vec(i); } return std::sqrt(norm); } /* -------------------------------------------------------------------------- */ template void MaterialElasticOrthotropic::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) + if (Dim == 3) Gamma = 1/(1 - nu12 * nu21 - nu23 * nu32 - nu31 * nu13 - 2 * nu21 * nu32 * nu13); - if (Dim == 2) + 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) + 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 --------------------------------- */ + /* 1) rotation of C into the global frame */ this->rotateCprime(); this->C.eig(this->eigC); } /* -------------------------------------------------------------------------- */ template inline void MaterialElasticOrthotropic::computePotentialEnergyOnQuad(const Matrix & grad_u, - const Matrix & sigma, - Real & epot) { + const Matrix & sigma, + Real & epot) { epot = .5 * sigma.doubleDot(grad_u); } /* -------------------------------------------------------------------------- */ - - template void MaterialElasticOrthotropic::computePotentialEnergy(ElementType el_type, - GhostType ghost_type) { + GhostType ghost_type) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(!this->finite_deformation,"finite deformation not possible in material orthotropic (TO BE IMPLEMENTED)"); if(ghost_type != _not_ghost) return; Array::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 void MaterialElasticOrthotropic::computePotentialEnergyByElement(ElementType type, UInt index, - Vector & epot_on_quad_points) { + Vector & epot_on_quad_points) { AKANTU_DEBUG_ASSERT(!this->finite_deformation,"finite deformation not possible in material orthotropic (TO BE IMPLEMENTED)"); Array::matrix_iterator gradu_it = this->gradu(type).begin(spatial_dimension, spatial_dimension); Array::matrix_iterator gradu_end = this->gradu(type).begin(spatial_dimension, spatial_dimension); Array::matrix_iterator stress_it = this->stress(type).begin(spatial_dimension, spatial_dimension); UInt nb_quadrature_points = this->model->getFEEngine().getNbQuadraturePoints(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 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); } } /* -------------------------------------------------------------------------- */ INSTANSIATE_MATERIAL(MaterialElasticOrthotropic); __END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_extra_includes.hh b/src/model/solid_mechanics/materials/material_extra_includes.hh index df43c0823..6259e76bd 100644 --- a/src/model/solid_mechanics/materials/material_extra_includes.hh +++ b/src/model/solid_mechanics/materials/material_extra_includes.hh @@ -1,59 +1,53 @@ /** * @file material_extra_includes.hh * * @author Nicolas Richart * * @date Wed Oct 31 16:24:42 2012 * * @brief Extra list of materials * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef AKANTU_CMAKE_LIST_MATERIALS // visco-elastic materials #include "material_stiffness_proportional.hh" -// elastic materials -#include "material_elastic_orthotropic.hh" -#include "material_elastic_linear_anisotropic.hh" - // damage materials #include "material_brittle.hh" #include "material_damage_iterative.hh" #include "material_damage_linear.hh" #include "material_vreepeerlings.hh" // plasticity #include "material_viscoplastic.hh" #endif #define AKANTU_EXTRA_MATERIAL_LIST \ ((2, (damage_linear , MaterialDamageLinear ))) \ ((2, (brittle , MaterialBrittle ))) \ ((2, (damage_iterative , MaterialDamageIterative ))) \ ((2, (vreepeerlings , MaterialVreePeerlings ))) \ ((2, (ve_stiffness_prop , MaterialStiffnessProportional ))) \ - ((2, (elastic_orthotropic, MaterialElasticOrthotropic ))) \ - ((2, (anisotropic , MaterialElasticLinearAnisotropic ))) \ ((2, (visco_plastic , MaterialViscoPlastic ))) diff --git a/src/model/solid_mechanics/solid_mechanics_model.cc b/src/model/solid_mechanics/solid_mechanics_model.cc index 4c044e585..f94974b1c 100644 --- a/src/model/solid_mechanics/solid_mechanics_model.cc +++ b/src/model/solid_mechanics/solid_mechanics_model.cc @@ -1,1829 +1,1826 @@ /** * @file solid_mechanics_model.cc * * @author Guillaume Anciaux * @author Nicolas Richart * * @date Tue Jul 27 18:15:37 2010 * * @brief Implementation of the SolidMechanicsModel class * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_math.hh" #include "aka_common.hh" #include "solid_mechanics_model.hh" #include "group_manager_inline_impl.cc" #include "dumpable_inline_impl.hh" #include "integration_scheme_2nd_order.hh" #include "element_group.hh" #include "static_communicator.hh" #include "dof_synchronizer.hh" #include "element_group.hh" #include #ifdef AKANTU_USE_MUMPS #include "solver_mumps.hh" #endif #ifdef AKANTU_USE_IOHELPER # include "dumper_field.hh" # include "dumper_paraview.hh" # include "dumper_homogenizing_field.hh" # include "dumper_material_internal_field.hh" # include "dumper_elemental_field.hh" # include "dumper_material_padders.hh" # include "dumper_element_partition.hh" # include "dumper_iohelper.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ -using std::cout; -using std::endl; - const SolidMechanicsModelOptions default_solid_mechanics_model_options(_explicit_lumped_mass, false); /* -------------------------------------------------------------------------- */ /** * 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(), time_step(NAN), f_m2a(1.0), mass_matrix(NULL), velocity_damping_matrix(NULL), stiffness_matrix(NULL), jacobian_matrix(NULL), element_index_by_material("element index by material", id), material_selector(new DefaultMaterialSelector(element_index_by_material)), is_default_material_selector(true), integrator(NULL), increment_flag(false), solver(NULL), synch_parallel(NULL), are_materials_instantiated(false) { AKANTU_DEBUG_IN(); createSynchronizerRegistry(this); registerFEEngineObject("SolidMechanicsFEEngine", mesh, spatial_dimension); this->displacement = NULL; this->mass = NULL; this->velocity = NULL; this->acceleration = NULL; this->force = NULL; this->residual = NULL; this->blocked_dofs = NULL; this->increment = NULL; this->increment_acceleration = NULL; this->dof_synchronizer = NULL; this->previous_displacement = NULL; materials.clear(); mesh.registerEventHandler(*this); #if defined(AKANTU_USE_IOHELPER) this->mesh.registerDumper("paraview_all", id, true); this->mesh.addDumpMesh(mesh, spatial_dimension, _not_ghost, _ek_regular); #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SolidMechanicsModel::~SolidMechanicsModel() { AKANTU_DEBUG_IN(); std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { delete *mat_it; } materials.clear(); delete integrator; delete solver; delete mass_matrix; delete velocity_damping_matrix; if(stiffness_matrix && stiffness_matrix != jacobian_matrix) delete stiffness_matrix; delete jacobian_matrix; delete synch_parallel; if(is_default_material_selector) { delete material_selector; material_selector = NULL; } AKANTU_DEBUG_OUT(); } void SolidMechanicsModel::setTimeStep(Real time_step) { this->time_step = time_step; #if defined(AKANTU_USE_IOHELPER) this->mesh.getDumper().setTimeStep(time_step); #endif } /* -------------------------------------------------------------------------- */ /* Initialisation */ /* -------------------------------------------------------------------------- */ /** * 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(options); method = smm_options.analysis_method; // initialize the vectors initArrays(); // set the initial condition to 0 force->clear(); velocity->clear(); acceleration->clear(); displacement->clear(); // initialize pcb if(pbc_pair.size()!=0) initPBC(); // initialize the time integration schemes switch(method) { case _explicit_lumped_mass: initExplicit(); break; case _explicit_consistent_mass: initSolver(); initExplicit(); break; case _implicit_dynamic: initImplicit(true); break; case _static: initImplicit(false); break; default: AKANTU_EXCEPTION("analysis method not recognised by SolidMechanicsModel"); break; } // initialize the materials if(this->parser->getLastParsedFile() != "") { instantiateMaterials(); } if(!smm_options.no_init_materials) { initMaterials(); } if(increment_flag) initBC(*this, *displacement, *increment, *force); else initBC(*this, *displacement, *force); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initParallel(MeshPartition * partition, DataAccessor * 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); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initFEEngineBoundary() { FEEngine & fem_boundary = getFEEngineBoundary(); fem_boundary.initShapeFunctions(_not_ghost); fem_boundary.initShapeFunctions(_ghost); fem_boundary.computeNormalsOnControlPoints(_not_ghost); fem_boundary.computeNormalsOnControlPoints(_ghost); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initExplicit(AnalysisMethod analysis_method) { AKANTU_DEBUG_IN(); //in case of switch from implicit to explicit if(!this->isExplicit()) method = analysis_method; if (integrator) delete integrator; integrator = new CentralDifference(); UInt nb_nodes = acceleration->getSize(); UInt nb_degree_of_freedom = acceleration->getNbComponent(); std::stringstream sstr; sstr << id << ":increment_acceleration"; increment_acceleration = &(alloc(sstr.str(), nb_nodes, nb_degree_of_freedom, Real())); AKANTU_DEBUG_OUT(); } void SolidMechanicsModel::initArraysPreviousDisplacment() { AKANTU_DEBUG_IN(); SolidMechanicsModel::setIncrementFlagOn(); UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_disp_t; sstr_disp_t << id << ":previous_displacement"; previous_displacement = &(alloc (sstr_disp_t.str(), nb_nodes, spatial_dimension, 0.)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Allocate all the needed vectors. By default their are not necessarily set to * 0 * */ void SolidMechanicsModel::initArrays() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_disp; sstr_disp << id << ":displacement"; // std::stringstream sstr_mass; sstr_mass << id << ":mass"; std::stringstream sstr_velo; sstr_velo << id << ":velocity"; std::stringstream sstr_acce; sstr_acce << id << ":acceleration"; std::stringstream sstr_forc; sstr_forc << id << ":force"; std::stringstream sstr_resi; sstr_resi << id << ":residual"; std::stringstream sstr_boun; sstr_boun << id << ":blocked_dofs"; displacement = &(alloc(sstr_disp.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); // mass = &(alloc(sstr_mass.str(), nb_nodes, spatial_dimension, 0)); velocity = &(alloc(sstr_velo.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); acceleration = &(alloc(sstr_acce.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); force = &(alloc(sstr_forc.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); residual = &(alloc(sstr_resi.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); blocked_dofs = &(alloc(sstr_boun.str(), nb_nodes, spatial_dimension, false)); std::stringstream sstr_curp; sstr_curp << id << ":current_position"; current_position = &(alloc(sstr_curp.str(), 0, spatial_dimension, REAL_INIT_VALUE)); for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(spatial_dimension, gt, _ek_not_defined); for(; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it, gt); element_index_by_material.alloc(nb_element, 2, *it, gt); } } dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension); dof_synchronizer->initLocalDOFEquationNumbers(); dof_synchronizer->initGlobalDOFEquationNumbers(); 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::iterator it = pbc_pair.begin(); std::map::iterator end = pbc_pair.end(); UInt dim = mesh.getSpatialDimension(); while(it != end) { for (UInt i=0; iregisterSynchronizer(*synch, _gst_smm_uv); synch_registry->registerSynchronizer(*synch, _gst_smm_mass); synch_registry->registerSynchronizer(*synch, _gst_smm_res); synch_registry->registerSynchronizer(*synch, _gst_for_dump); changeLocalEquationNumberForPBC(pbc_pair, mesh.getSpatialDimension()); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateCurrentPosition() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); current_position->resize(nb_nodes); Real * current_position_val = current_position->storage(); Real * position_val = mesh.getNodes().storage(); Real * displacement_val = displacement->storage(); /// compute current_position = initial_position + displacement memcpy(current_position_val, position_val, nb_nodes*spatial_dimension*sizeof(Real)); for (UInt n = 0; n < nb_nodes*spatial_dimension; ++n) { *current_position_val++ += *displacement_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initializeUpdateResidualData() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); residual->resize(nb_nodes); /// copy the forces in residual for boundary conditions memcpy(residual->storage(), force->storage(), nb_nodes*spatial_dimension*sizeof(Real)); // start synchronization synch_registry->asynchronousSynchronize(_gst_smm_uv); synch_registry->waitEndSynchronize(_gst_smm_uv); updateCurrentPosition(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* Explicit scheme */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /** * This function compute the second member of the motion equation. That is to * say the sum of forces @f$ r = F_{ext} - F_{int} @f$. @f$ F_{ext} @f$ is given * by the user in the force vector, and @f$ F_{int} @f$ is computed as @f$ * F_{int} = \int_{\Omega} N \sigma d\Omega@f$ * */ void SolidMechanicsModel::updateResidual(bool need_initialize) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Assemble the internal forces"); // f = f_ext - f_int // f = f_ext if(need_initialize) initializeUpdateResidualData(); AKANTU_DEBUG_INFO("Compute local stresses"); std::vector::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 */ synch_registry->asynchronousSynchronize(_gst_mnl_for_average); AKANTU_DEBUG_INFO("Compute non local stresses for local elements"); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllNonLocalStresses(_not_ghost); } AKANTU_DEBUG_INFO("Wait distant non local stresses"); synch_registry->waitEndSynchronize(_gst_mnl_for_average); AKANTU_DEBUG_INFO("Compute non local stresses for ghosts elements"); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllNonLocalStresses(_ghost); } #endif /* ------------------------------------------------------------------------ */ /* assembling the forces internal */ // communicate the stress AKANTU_DEBUG_INFO("Send data for residual assembly"); synch_registry->asynchronousSynchronize(_gst_smm_stress); AKANTU_DEBUG_INFO("Assemble residual for local elements"); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.assembleResidual(_not_ghost); } AKANTU_DEBUG_INFO("Wait distant stresses"); // finalize communications synch_registry->waitEndSynchronize(_gst_smm_stress); AKANTU_DEBUG_INFO("Assemble residual for ghost elements"); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.assembleResidual(_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::computeStresses() { if (isExplicit()) { // start synchronization synch_registry->asynchronousSynchronize(_gst_smm_uv); synch_registry->waitEndSynchronize(_gst_smm_uv); // compute stresses on all local elements for each materials std::vector::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 */ synch_registry->asynchronousSynchronize(_gst_mnl_for_average); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllNonLocalStresses(_not_ghost); } synch_registry->waitEndSynchronize(_gst_mnl_for_average); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllNonLocalStresses(_ghost); } #endif } else { std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllStressesFromTangentModuli(_not_ghost); } } } /* -------------------------------------------------------------------------- */ 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 * Ma = new Array(*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 * Cv = new Array(*velocity); *Cv *= *velocity_damping_matrix; *residual -= *Cv; delete Cv; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::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(*increment_acceleration); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::solveLumped(Array & x, const Array & A, const Array & b, const Array & 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 SolidMechanicsModel::explicitPred() { AKANTU_DEBUG_IN(); if(increment_flag) { if(previous_displacement) increment->copy(*previous_displacement); else increment->copy(*displacement); } AKANTU_DEBUG_ASSERT(integrator,"itegrator should have been allocated: " << "have called initExplicit ? " << "or initImplicit ?"); integrator->integrationSchemePred(time_step, *displacement, *velocity, *acceleration, *blocked_dofs); if(increment_flag) { Real * inc_val = increment->storage(); Real * dis_val = displacement->storage(); UInt nb_degree_of_freedom = displacement->getSize() * displacement->getNbComponent(); for (UInt n = 0; n < nb_degree_of_freedom; ++n) { *inc_val = *dis_val - *inc_val; inc_val++; dis_val++; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::explicitCorr() { AKANTU_DEBUG_IN(); integrator->integrationSchemeCorrAccel(time_step, *displacement, *velocity, *acceleration, *blocked_dofs, *increment_acceleration); if(previous_displacement) previous_displacement->copy(*displacement); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::solveStep() { AKANTU_DEBUG_IN(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeSolveStepEvent(method)); this->explicitPred(); this->updateResidual(); this->updateAcceleration(); this->explicitCorr(); EventManager::sendEvent(SolidMechanicsModelEvent::AfterSolveStepEvent(method)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* Implicit scheme */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /** * Initialize the solver and create the sparse matrices needed. * */ void SolidMechanicsModel::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 << id << ":jacobian_matrix"; jacobian_matrix = new SparseMatrix(nb_global_nodes * spatial_dimension, _symmetric, sstr.str(), memory_id); jacobian_matrix->buildProfile(mesh, *dof_synchronizer, spatial_dimension); if (!isExplicit()) { delete stiffness_matrix; 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 if(solver) solver->initialize(options); #endif //AKANTU_HAS_SOLVER } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initJacobianMatrix() { #ifdef AKANTU_USE_MUMPS // @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; std::stringstream sstr_sti; sstr_sti << id << ":jacobian_matrix"; jacobian_matrix = new SparseMatrix(*stiffness_matrix, sstr_sti.str(), memory_id); 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); #else AKANTU_DEBUG_ERROR("You should at least activate one solver."); #endif } /* -------------------------------------------------------------------------- */ /** * Initialize the implicit solver, either for dynamic or static cases, * * @param dynamic */ void SolidMechanicsModel::initImplicit(bool dynamic, SolverOptions & solver_options) { AKANTU_DEBUG_IN(); method = dynamic ? _implicit_dynamic : _static; if (!increment) setIncrementFlagOn(); initSolver(solver_options); if(method == _implicit_dynamic) { if(integrator) delete integrator; integrator = new TrapezoidalRule2(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initialAcceleration() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Solving Ma = f"); Solver * acc_solver = NULL; std::stringstream sstr; sstr << id << ":tmp_mass_matrix"; SparseMatrix * tmp_mass = new SparseMatrix(*mass_matrix, sstr.str(), memory_id); #ifdef AKANTU_USE_MUMPS std::stringstream sstr_solver; sstr << id << ":solver_mass_matrix"; acc_solver = new SolverMumps(*mass_matrix, sstr_solver.str()); dof_synchronizer->initScatterGatherCommunicationScheme(); #else AKANTU_DEBUG_ERROR("You should at least activate one solver."); #endif //AKANTU_USE_MUMPS acc_solver->initialize(); tmp_mass->applyBoundary(*blocked_dofs); acc_solver->setRHS(*residual); acc_solver->solve(*acceleration); delete acc_solver; delete tmp_mass; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleStiffnessMatrix() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Assemble the new stiffness matrix."); stiffness_matrix->clear(); // call compute stiffness matrix on each local elements std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->assembleStiffnessMatrix(_not_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseMatrix & SolidMechanicsModel::initVelocityDampingMatrix() { if(!velocity_damping_matrix) velocity_damping_matrix = new SparseMatrix(*jacobian_matrix, id + ":velocity_damping_matrix", memory_id); return *velocity_damping_matrix; } /* -------------------------------------------------------------------------- */ template<> bool SolidMechanicsModel::testConvergence<_scc_increment>(Real tolerance, Real & error){ AKANTU_DEBUG_IN(); UInt nb_nodes = displacement->getSize(); UInt nb_degree_of_freedom = displacement->getNbComponent(); error = 0; Real norm[2] = {0., 0.}; Real * increment_val = increment->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); Real * displacement_val = displacement->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] += *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 goes wrong in the solve phase"); if (norm[1] < Math::getTolerance()) { error = norm[0]; AKANTU_DEBUG_OUT(); // cout<<"Error 1: "< Math::getTolerance()) error = norm[0] / norm[1]; else error = norm[0]; //In case the total displacement is zero! // cout<<"Error 2: "< bool SolidMechanicsModel::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 < spatial_dimension; ++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); } /* -------------------------------------------------------------------------- */ template<> bool SolidMechanicsModel::testConvergence<_scc_residual_mass_wgh>(Real tolerance, Real & norm) { AKANTU_DEBUG_IN(); UInt nb_nodes = residual->getSize(); norm = 0; Real * residual_val = residual->storage(); Real * mass_val = this->mass->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 < spatial_dimension; ++d) { if(!(*blocked_dofs_val)) { norm += *residual_val * *residual_val/(*mass_val * *mass_val); } blocked_dofs_val++; residual_val++; mass_val++; } } else { blocked_dofs_val += spatial_dimension; residual_val += spatial_dimension; mass_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 SolidMechanicsModel::testConvergenceResidual(Real tolerance){ AKANTU_DEBUG_IN(); Real error=0; bool res = this->testConvergence<_scc_residual>(tolerance, error); AKANTU_DEBUG_OUT(); return res; } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceResidual(Real tolerance, Real & error){ AKANTU_DEBUG_IN(); bool res = this->testConvergence<_scc_residual>(tolerance, error); AKANTU_DEBUG_OUT(); return res; } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceIncrement(Real tolerance){ AKANTU_DEBUG_IN(); Real error=0; bool res = this->testConvergence<_scc_increment>(tolerance, error); AKANTU_DEBUG_OUT(); return res; } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceIncrement(Real tolerance, Real & error){ AKANTU_DEBUG_IN(); bool res = this->testConvergence<_scc_increment>(tolerance, error); AKANTU_DEBUG_OUT(); return res; } /* -------------------------------------------------------------------------- */ 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(); AKANTU_DEBUG_ASSERT(previous_displacement,"The previous displacement has to be initialized." << " Are you working with Finite or Ineslactic deformations?"); UInt nb_nodes = displacement->getSize(); UInt nb_degree_of_freedom = displacement->getNbComponent() * nb_nodes; Real * incr_val = increment->storage(); Real * disp_val = displacement->storage(); Real * prev_disp_val = previous_displacement->storage(); for (UInt j = 0; j < nb_degree_of_freedom; ++j, ++disp_val, ++incr_val, ++prev_disp_val) *incr_val = (*disp_val - *prev_disp_val); 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(); } /* -------------------------------------------------------------------------- */ /* Information */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::synchronizeBoundaries() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(synch_registry,"Synchronizer registry was not initialized." << " Did you call initParallel?"); synch_registry->synchronize(_gst_smm_boundary); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::synchronizeResidual() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(synch_registry,"Synchronizer registry was not initialized." << " Did you call initPBC?"); synch_registry->synchronize(_gst_smm_res); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::setIncrementFlagOn() { AKANTU_DEBUG_IN(); if(!increment) { UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_inc; sstr_inc << id << ":increment"; increment = &(alloc(sstr_inc.str(), nb_nodes, spatial_dimension, 0.)); } increment_flag = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getStableTimeStep() { AKANTU_DEBUG_IN(); Real min_dt = getStableTimeStep(_not_ghost); /// reduction min over all processors StaticCommunicator::getStaticCommunicator().allReduce(&min_dt, 1, _so_min); AKANTU_DEBUG_OUT(); return min_dt; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getStableTimeStep(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); Material ** mat_val = &(materials.at(0)); Real min_dt = std::numeric_limits::max(); updateCurrentPosition(); Element elem; elem.ghost_type = ghost_type; elem.kind = _ek_regular; Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type); for(; it != end; ++it) { elem.type = *it; UInt nb_nodes_per_element = mesh.getNbNodesPerElement(*it); UInt nb_element = mesh.getNbElement(*it); Array::iterator< Vector > eibm = element_index_by_material(*it, ghost_type).begin(2); Array X(0, nb_nodes_per_element*spatial_dimension); FEEngine::extractNodalToElementField(mesh, *current_position, X, *it, _not_ghost); Array::matrix_iterator X_el = X.begin(spatial_dimension, nb_nodes_per_element); for (UInt el = 0; el < nb_element; ++el, ++X_el, ++eibm) { elem.element = (*eibm)(1); Real el_h = getFEEngine().getElementInradius(*X_el, *it); Real el_c = mat_val[(*eibm)(0)]->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::getPotentialEnergy() { AKANTU_DEBUG_IN(); Real energy = 0.; /// call update residual on each local elements std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { energy += (*mat_it)->getPotentialEnergy(); } /// reduction sum over all processors StaticCommunicator::getStaticCommunicator().allReduce(&energy, 1, _so_sum); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getKineticEnergy() { AKANTU_DEBUG_IN(); if (!mass && !mass_matrix) AKANTU_DEBUG_ERROR("No function called to assemble the mass matrix."); Real ekin = 0.; UInt nb_nodes = mesh.getNbNodes(); Real * vel_val = velocity->storage(); Real * mass_val = mass->storage(); for (UInt n = 0; n < nb_nodes; ++n) { 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; for (UInt i = 0; i < spatial_dimension; ++i) { if (count_node) mv2 += *vel_val * *vel_val * *mass_val; vel_val++; mass_val++; } ekin += mv2; } StaticCommunicator::getStaticCommunicator().allReduce(&ekin, 1, _so_sum); AKANTU_DEBUG_OUT(); return ekin * .5; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getKineticEnergy(const ElementType & type, UInt index) { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = getFEEngine().getNbQuadraturePoints(type); Array vel_on_quad(nb_quadrature_points, spatial_dimension); Array filter_element(1, 1, index); getFEEngine().interpolateOnQuadraturePoints(*velocity, vel_on_quad, spatial_dimension, type, _not_ghost, filter_element); Array::vector_iterator vit = vel_on_quad.begin(spatial_dimension); Array::vector_iterator vend = vel_on_quad.end(spatial_dimension); Vector rho_v2(nb_quadrature_points); Real rho = materials[element_index_by_material(type)(index, 0)]->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(); Real * velo = velocity->storage(); Real * forc = force->storage(); Real * resi = residual->storage(); bool * boun = blocked_dofs->storage(); Real work = 0.; UInt nb_nodes = mesh.getNbNodes(); for (UInt n = 0; n < nb_nodes; ++n) { 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; for (UInt i = 0; i < spatial_dimension; ++i) { if (count_node) { if(*boun) work -= *resi * *velo * time_step; else work += *forc * *velo * time_step; } ++velo; ++forc; ++resi; ++boun; } } StaticCommunicator::getStaticCommunicator().allReduce(&work, 1, _so_sum); 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.; std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { energy += (*mat_it)->getEnergy(energy_id); } /// reduction sum over all processors StaticCommunicator::getStaticCommunicator().allReduce(&energy, 1, _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); } std::vector::iterator mat_it; Vector mat = element_index_by_material(type, _not_ghost).begin(2)[index]; Real energy = materials[mat(0)]->getEnergy(energy_id, type, mat(1)); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onNodesAdded(const Array & nodes_list, __attribute__((unused)) const NewNodesEvent & event) { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); if(displacement) displacement->resize(nb_nodes); if(mass ) mass ->resize(nb_nodes); if(velocity ) velocity ->resize(nb_nodes); if(acceleration) acceleration->resize(nb_nodes); if(force ) force ->resize(nb_nodes); if(residual ) residual ->resize(nb_nodes); if(blocked_dofs) blocked_dofs->resize(nb_nodes); if(previous_displacement) previous_displacement->resize(nb_nodes); if(increment_acceleration) increment_acceleration->resize(nb_nodes); if(increment) increment->resize(nb_nodes); if(current_position) current_position->resize(nb_nodes); delete dof_synchronizer; dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension); dof_synchronizer->initLocalDOFEquationNumbers(); dof_synchronizer->initGlobalDOFEquationNumbers(); std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->onNodesAdded(nodes_list, event); } if (method != _explicit_lumped_mass) { delete stiffness_matrix; delete jacobian_matrix; delete solver; SolverOptions solver_options; initImplicit((method == _implicit_dynamic), solver_options); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onElementsAdded(const Array & element_list, const NewElementsEvent & event) { AKANTU_DEBUG_IN(); getFEEngine().initShapeFunctions(_not_ghost); getFEEngine().initShapeFunctions(_ghost); Array::const_iterator it = element_list.begin(); Array::const_iterator end = element_list.end(); /// \todo have rules to choose the correct material UInt mat_id = 0; UInt * mat_id_vect = NULL; try { const NewMaterialElementsEvent & event_mat = dynamic_cast(event); mat_id_vect = event_mat.getMaterialList().storage(); } catch(...) { } for (UInt el = 0; it != end; ++it, ++el) { const Element & elem = *it; if(mat_id_vect) mat_id = mat_id_vect[el]; else mat_id = (*material_selector)(elem); Material & mat = *materials[mat_id]; UInt mat_index = mat.addElement(elem.type, elem.element, elem.ghost_type); Vector id(2); id[0] = mat_id; id[1] = mat_index; if(!element_index_by_material.exists(elem.type, elem.ghost_type)) element_index_by_material.alloc(0, 2, elem.type, elem.ghost_type); element_index_by_material(elem.type, elem.ghost_type).push_back(id); } std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->onElementsAdded(element_list, event); } if(method != _explicit_lumped_mass) AKANTU_DEBUG_TO_IMPLEMENT(); assembleMassLumped(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onElementsRemoved(__attribute__((unused)) const Array & element_list, const ElementTypeMapArray & new_numbering, const RemovedElementsEvent & event) { // MeshUtils::purifyMesh(mesh); getFEEngine().initShapeFunctions(_not_ghost); getFEEngine().initShapeFunctions(_ghost); std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->onElementsRemoved(element_list, new_numbering, event); } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onNodesRemoved(__attribute__((unused)) const Array & element_list, const Array & 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(force ) mesh.removeNodesFromArray(*force , new_numbering); if(residual ) mesh.removeNodesFromArray(*residual , new_numbering); if(blocked_dofs) mesh.removeNodesFromArray(*blocked_dofs, new_numbering); if(increment_acceleration) mesh.removeNodesFromArray(*increment_acceleration, new_numbering); if(increment) mesh.removeNodesFromArray(*increment , new_numbering); delete dof_synchronizer; dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension); dof_synchronizer->initLocalDOFEquationNumbers(); dof_synchronizer->initGlobalDOFEquationNumbers(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::reassignMaterial() { AKANTU_DEBUG_IN(); std::vector< Array > element_to_add (materials.size()); std::vector< Array > element_to_remove(materials.size()); 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; Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_regular); Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type, _ek_regular); for(; it != end; ++it) { ElementType type = *it; element.type = type; element.kind = Mesh::getKind(type); UInt nb_element = mesh.getNbElement(type, ghost_type); Array & el_index_by_mat = element_index_by_material(type, ghost_type); for (UInt el = 0; el < nb_element; ++el) { element.element = el; UInt old_material = el_index_by_mat(el, 0); 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); } } } } std::vector::iterator mat_it; UInt mat_index = 0; for(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(); } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::isInternal(const std::string & field_name, const ElementKind & element_kind){ bool is_internal = false; /// check if at least one material contains field_id as an internal for (UInt m = 0; m < materials.size() && !is_internal; ++m) { is_internal |= materials[m]->isInternal(field_name, element_kind); } return is_internal; } /* -------------------------------------------------------------------------- */ ElementTypeMap 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 (UInt m = 0; m < materials.size() ; ++m) { if (materials[m]->isInternal(field_name, element_kind)) return materials[m]->getInternalDataPerElem(field_name,element_kind); } return ElementTypeMap(); } /* -------------------------------------------------------------------------- */ ElementTypeMapArray & SolidMechanicsModel::flattenInternal(const std::string & field_name, const ElementKind & kind){ std::pair key(field_name,kind); if (this->registered_internals.count(key) == 0){ this->registered_internals[key] = new ElementTypeMapArray(field_name,this->id); } ElementTypeMapArray * internal_flat = this->registered_internals[key]; for (UInt m = 0; m < materials.size(); ++m) materials[m]->flattenInternal(field_name,*internal_flat,_not_ghost,kind); return *internal_flat; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::flattenAllRegisteredInternals(const ElementKind & kind){ std::map,ElementTypeMapArray *> ::iterator it = this->registered_internals.begin(); std::map,ElementTypeMapArray *>::iterator end = this->registered_internals.end(); while (it != end){ if (kind == it->first.second) this->flattenInternal(it->first.first,kind); ++it; } } /* -------------------------------------------------------------------------- */ 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 ElementKind & kind){ dumper::Field * field = NULL; if(field_name == "partitions") field = mesh.createElementalField(mesh.getConnectivities(),group_name,this->spatial_dimension,kind); else if(field_name == "element_index_by_material") field = mesh.createElementalField(element_index_by_material,group_name,this->spatial_dimension,kind); else { bool is_internal = this->isInternal(field_name,kind); if (is_internal) { ElementTypeMap nb_data_per_elem = this->getInternalDataPerElem(field_name,kind); ElementTypeMapArray & internal_flat = this->flattenInternal(field_name,kind); field = mesh.createElementalField(internal_flat, group_name, this->spatial_dimension,kind,nb_data_per_elem); //treat the paddings if (padding_flag){ if (field_name == "stress"){ if (this->spatial_dimension == 2) { dumper::StressPadder<2> * foo = new dumper::StressPadder<2>(*this); field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); } } // else if (field_name == "strain"){ // if (this->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* > real_nodal_fields; real_nodal_fields["displacement" ] = displacement; real_nodal_fields["mass" ] = mass; real_nodal_fields["velocity" ] = velocity; real_nodal_fields["acceleration" ] = acceleration; real_nodal_fields["force" ] = force; real_nodal_fields["residual" ] = residual; real_nodal_fields["increment" ] = increment; dumper::Field * field = NULL; if (padding_flag) field = mesh.createNodalField(real_nodal_fields[field_name],group_name, 3); else field = 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, bool padding_flag) { std::map* > 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(const std::string & field_name, const std::string & group_name, bool padding_flag, const ElementKind & kind){ return NULL; } /* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel::createNodalFieldReal(const std::string & field_name, const std::string & group_name, bool padding_flag) { return NULL; } /* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel::createNodalFieldBool(const std::string & field_name, const std::string & group_name, bool padding_flag) { return NULL; } #endif /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(const std::string & dumper_name) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); synch_registry->synchronize(_gst_for_dump); mesh.dump(dumper_name); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(const std::string & dumper_name, UInt step) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); synch_registry->synchronize(_gst_for_dump); mesh.dump(dumper_name, step); } /* ------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(const std::string & dumper_name, Real time, UInt step) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); synch_registry->synchronize(_gst_for_dump); 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::computeCauchyStresses() { AKANTU_DEBUG_IN(); // call compute stiffness matrix on each local elements std::vector::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 SolidMechanicsModel::saveStressAndStrainBeforeDamage() { EventManager::sendEvent(SolidMechanicsModelEvent::BeginningOfDamageIterationEvent()); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateEnergiesAfterDamage() { EventManager::sendEvent(SolidMechanicsModelEvent::AfterDamageEvent()); } /* -------------------------------------------------------------------------- */ 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); force ->printself(stream, indent + 2); residual ->printself(stream, indent + 2); blocked_dofs->printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + connectivity type information [" << std::endl; element_index_by_material.printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + materials [" << std::endl; std::vector::const_iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { const Material & mat = *(*mat_it); mat.printself(stream, indent + 1); } stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/test/test_contact/acurnier_2D_1.cc b/test/test_contact/acurnier_2D_1.cc index 501b09df6..e9f720b73 100644 --- a/test/test_contact/acurnier_2D_1.cc +++ b/test/test_contact/acurnier_2D_1.cc @@ -1,106 +1,106 @@ /** * @file acurnier_2D_1.cc * * @author Alejandro M. Aragón * * @date Thu Sep 04 16:30:00 2014 * * @brief This file implements the first simple test suggested by Alain Curnier * for the verification of the implicit contact implementation of the Augmented * lagrangian formulation * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #include "contact_impl.hh" using namespace akantu; int main(int argc, char *argv[]) { // set dimension static const UInt dim = 2; // type definitions typedef SolidMechanicsModel model_type; typedef Contact > contact_type; initialize("material.dat", argc, argv); // create meshes Mesh mesh(dim); // read meshes mesh.read("acurnier_2D_1.msh"); // create models model_type model(mesh); SolidMechanicsModelOptions opt(_static); MeshDataMaterialSelector material_selector("physical_names", model); model.setMaterialSelector(material_selector); // initialize material model.initFull(opt); model.updateCurrentPosition(); // create data structure that holds contact data contact_type cd(argc, argv, model); // set Paraview output resluts model.setBaseName("contact"); model.addDumpFieldVector("displacement"); mesh.createGroupsFromMeshData("physical_names"); cd.addSlave(4); cd.addArea(4, 1.0); // add master surface to find pairs cd.searchSurface("Contact"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Top"); // fix entire contact body - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Bottom"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_y), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _y), "Bottom"); Real U = 0.5; Real Du = 0.01; for (Real u = Du; u <= U; u += Du) { - model.applyBC(BC::Dirichlet::FixedValue(-u, BC::_y), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(-u, _y), "Top"); // solve contact step (no need to call solve on the model object) solveContactStep<_generalized_newton>(cd); } cout<<"Force: "<< cd.getForce()< * * @date Thu Sep 04 16:30:00 2014 * * @brief This file implements the first simple test suggested by Alain Curnier * for the verification of the implicit contact implementation of the Augmented * lagrangian formulation * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #include "contact_impl.hh" using namespace akantu; int main(int argc, char *argv[]) { // set dimension static const UInt dim = 2; // type definitions typedef SolidMechanicsModel model_type; typedef Contact > contact_type; initialize("material.dat", argc, argv); // create meshes Mesh mesh(dim); // read meshes mesh.read("acurnier_2D_2.msh"); // create models model_type model(mesh); SolidMechanicsModelOptions opt(_static); MeshDataMaterialSelector material_selector("physical_names", model); model.setMaterialSelector(material_selector); // initialize material model.initFull(opt); model.updateCurrentPosition(); // create data structure that holds contact data contact_type cd(argc, argv, model); // set Paraview output resluts model.setBaseName("contact"); model.addDumpFieldVector("displacement"); // model.addDumpField("element_index_by_material"); mesh.createGroupsFromMeshData("physical_names"); cd.addSlave(4); cd.addSlave(7); cd.addArea(4, 1.0); cd.addArea(7, 1.0); // add master surface to find pairs cd.searchSurface("Contact"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Top"); // fix entire contact body - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Bottom"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_y), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _y), "Bottom"); Real U = 0.5; Real Du = 0.01; for (Real u = Du; u <= U; u += Du) { - model.applyBC(BC::Dirichlet::FixedValue(-u, BC::_y), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(-u, _y), "Top"); // solve contact step (no need to call solve on the model object) solveContactStep<_generalized_newton>(cd); } cout<<"Force: "<< cd.getForce()< * * @date Thu Sep 04 16:30:00 2014 * * @brief This file implements the third simple test suggested by Alain Curnier * for the verification of the implicit contact implementation of the Augmented * lagrangian formulation * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #include "contact_impl.hh" using namespace akantu; int main(int argc, char *argv[]) { // set dimension static const UInt dim = 2; // type definitions typedef SolidMechanicsModel model_type; typedef Contact > contact_type; initialize("material.dat", argc, argv); // create meshes Mesh mesh(dim); // read meshes mesh.read("acurnier_2D_3.msh"); // create models model_type model(mesh); SolidMechanicsModelOptions opt(_static); MeshDataMaterialSelector material_selector("physical_names", model); model.setMaterialSelector(material_selector); // initialize material model.initFull(opt); model.updateCurrentPosition(); // create data structure that holds contact data contact_type cd(argc, argv, model); // set Paraview output resluts model.setBaseName("contact"); model.addDumpFieldVector("displacement"); mesh.createGroupsFromMeshData("physical_names"); cd.addSlave(4); cd.addSlave(7); cd.addSlave(9); cd.addArea(4, 1.0); cd.addArea(7, 1.0); cd.addArea(9, 1.0); // add master surface to find pairs cd.searchSurface("Contact"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Top"); // fix entire contact body - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Bottom"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_y), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _y), "Bottom"); Real U = 0.5; Real Du = 0.01; for (Real u = Du; u <= U; u += Du) { - model.applyBC(BC::Dirichlet::FixedValue(-u, BC::_y), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(-u, _y), "Top"); // solve contact step (no need to call solve on the model object) solveContactStep<_generalized_newton>(cd); } cout << "Force: " << cd.getForce() << endl; // finalize simulation finalize(); return EXIT_SUCCESS; } diff --git a/test/test_contact/acurnier_3D_1.cc b/test/test_contact/acurnier_3D_1.cc index dc4184312..6edd5edb2 100644 --- a/test/test_contact/acurnier_3D_1.cc +++ b/test/test_contact/acurnier_3D_1.cc @@ -1,108 +1,108 @@ /** * @file acurnier_3D_1.cc * * @author Alejandro M. Aragón * * @date Thu Sep 10 16:30:00 2014 * * @brief This file implements the fourth simple test suggested by Alain * Curnier for the verification of the implicit contact implementation of the * Augmented lagrangian formulation * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #include "contact_impl.hh" using namespace akantu; int main(int argc, char *argv[]) { // set dimension static const UInt dim = 3; // type definitions typedef SolidMechanicsModel model_type; typedef Contact > contact_type; initialize("material.dat", argc, argv); // create meshes Mesh mesh(dim); // read meshes mesh.read("acurnier_3D_1.msh"); // create models model_type model(mesh); SolidMechanicsModelOptions opt(_static); MeshDataMaterialSelector material_selector("physical_names", model); model.setMaterialSelector(material_selector); // initialize material model.initFull(opt); model.updateCurrentPosition(); // create data structure that holds contact data contact_type cd(argc, argv, model); // set Paraview output resluts model.setBaseName("contact"); model.addDumpFieldVector("displacement"); mesh.createGroupsFromMeshData("physical_names"); cd.addSlave(4); cd.addArea(4, 1.0); // add master surface to find pairs cd.searchSurface("Contact"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Top"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_z), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(0., _z), "Top"); // fix entire contact body - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Bottom"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_y), "Bottom"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_z), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _y), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _z), "Bottom"); Real U = 0.5; Real Du = 0.01; for (Real u = Du; u <= U; u += Du) { - model.applyBC(BC::Dirichlet::FixedValue(-u, BC::_y), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(-u, _y), "Top"); // solve contact step (no need to call solve on the model object) solveContactStep<_generalized_newton>(cd); } cout<<"Force: "<< cd.getForce()< * * @date Thu Sep 10 16:30:00 2014 * * @brief This file implements the fifth simple test suggested by Alain * Curnier for the verification of the implicit contact implementation of the * Augmented lagrangian formulation * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #include "contact_impl.hh" using namespace akantu; int main(int argc, char *argv[]) { // set dimension static const UInt dim = 3; // type definitions typedef SolidMechanicsModel model_type; typedef Contact > contact_type; initialize("material.dat", argc, argv); // create meshes Mesh mesh(dim); // read meshes mesh.read("acurnier_3D_2.msh"); // create models model_type model(mesh); SolidMechanicsModelOptions opt(_static); MeshDataMaterialSelector material_selector("physical_names", model); model.setMaterialSelector(material_selector); // initialize material model.initFull(opt); model.updateCurrentPosition(); // create data structure that holds contact data contact_type cd(argc, argv, model); // set Paraview output resluts model.setBaseName("contact"); model.addDumpFieldVector("displacement"); mesh.createGroupsFromMeshData("physical_names"); cd.addSlave(5); cd.addSlave(6); cd.addSlave(11); cd.addArea(5, 1.0); cd.addArea(6, 1.0); cd.addArea(11, 1.0); // add master surface to find pairs cd.searchSurface("Contact"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Top"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_z), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(0., _z), "Top"); // fix entire contact body - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Bottom"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_y), "Bottom"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_z), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _y), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _z), "Bottom"); Real U = 0.5; Real Du = 0.01; for (Real u = Du; u <= U; u += Du) { - model.applyBC(BC::Dirichlet::FixedValue(-u, BC::_y), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(-u, _y), "Top"); // solve contact step (no need to call solve on the model object) solveContactStep<_generalized_newton>(cd); } cout<<"Force: "<< cd.getForce()< * * @date Thu Sep 10 16:30:00 2014 * * @brief This file implements the sixth simple test suggested by Alain * Curnier for the verification of the implicit contact implementation of the * Augmented lagrangian formulation * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #include "contact_impl.hh" using namespace akantu; int main(int argc, char *argv[]) { // set dimension static const UInt dim = 3; // type definitions typedef SolidMechanicsModel model_type; typedef Contact > contact_type; initialize("material.dat", argc, argv); // create meshes Mesh mesh(dim); // read meshes mesh.read("acurnier_3D_3.msh"); // create models model_type model(mesh); SolidMechanicsModelOptions opt(_static); MeshDataMaterialSelector material_selector("physical_names", model); model.setMaterialSelector(material_selector); // initialize material model.initFull(opt); model.updateCurrentPosition(); // create data structure that holds contact data contact_type cd(argc, argv, model); // set Paraview output resluts model.setBaseName("contact"); model.addDumpFieldVector("displacement"); mesh.createGroupsFromMeshData("physical_names"); cd.addSlave(4); cd.addSlave(5); cd.addSlave(6); cd.addSlave(7); cd.addSlave(20); cd.addArea(4, 1.0); cd.addArea(5, 1.0); cd.addArea(6, 1.0); cd.addArea(7, 1.0); cd.addArea(20, 1.0); // add master surface to find pairs cd.searchSurface("Contact"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Top"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_z), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(0., _z), "Top"); // fix entire contact body - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Bottom"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_y), "Bottom"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_z), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _y), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _z), "Bottom"); Real U = 0.5; Real Du = 0.01; for (Real u = Du; u <= U; u += Du) { - model.applyBC(BC::Dirichlet::FixedValue(-u, BC::_y), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(-u, _y), "Top"); // solve contact step (no need to call solve on the model object) solveContactStep<_generalized_newton>(cd); } cout<<"Force: "<< cd.getForce()< * * @date Mon Mar 24 11:30:00 2014 * * @brief This file tests for the Hertz solution in 2D * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #include "contact_impl.hh" #include "dumpable_inline_impl.hh" using namespace akantu; using std::cout; using std::endl; using std::setw; using std::setprecision; int main(int argc, char *argv[]) { // set dimension static const UInt dim = 2; // type definitions typedef Point point_type; typedef BoundingBox bbox_type; typedef SolidMechanicsModel model_type; typedef ModelElement master_type; typedef Contact > contact_type; initialize("steel.dat", argc, argv); // create mesh Mesh mesh(dim); // read mesh mesh.read("hertz_2D.msh"); // create model model_type model(mesh); SolidMechanicsModelOptions opt(_static); // initialize material model.initFull(opt); model.updateCurrentPosition(); // create data structure that holds contact data contact_type cd(argc, argv, model); // optimal value of penalty multiplier cd[Alpha] = 0.4; // set Paraview output resluts model.setBaseName("contact"); model.addDumpFieldVector("displacement"); // use bounding box to minimize slave-master pairs Real r0 = 0.5; Real r1 = 0.15; point_type c1(-r0/2,-r1/2); point_type c2( r0/2, r1/2); bbox_type bb(c1, c2); // get physical names from mesh Array &coords = mesh.getNodes(); mesh.createGroupsFromMeshData("physical_names"); // compute areas for slave nodes that are used for the computation of contact pressures model.applyBC(BC::Neumann::FromHigherDim(Matrix::eye(2,1.)), "contact_surface"); // NOTE: the areas are computed by assigning a unit pressure to the contact surface, // then the magnitude of the resulting force vector at nodes gives its associated area Array& areas = model.getForce(); // add slave-master pairs and store slave node areas ElementGroup &eg = mesh.getElementGroup("contact_surface"); ElementGroup &rs = mesh.getElementGroup("rigid"); for (auto nit = eg.node_begin(); nit != eg.node_end(); ++nit) { // get point of slave node point_type n(&coords(*nit)); // process only if within bounding box if (bb & n) { // loop over element types for (ElementGroup::type_iterator tit = rs.firstType(); tit != rs.lastType(); ++tit) // loop over elements of the rigid surface for (ElementGroup::const_element_iterator it = rs.element_begin(*tit); it != rs.element_end(*tit); ++it) { // create master element master_type m(model, _segment_2, *it); assert(has_projection(n,m.point<2>(0),m.point<2>(1))); // add slave-master pair cd.addPair(*nit,m); } // compute and add area to slave node Real a = 0.; for (UInt i=0; i(cd); data[0][k] = delta; data[1][k] = cd.getForce(); data[2][k] = cd.getMaxPressure(); ++k; } // print results size_t w = 10; cout< * * @date Fri Apr 4 11:30:00 2014 * * @brief This file tests for the Hertz solution in 3D * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #include "contact_impl.hh" #include "dumpable_inline_impl.hh" - using namespace akantu; using std::cout; using std::endl; using std::setw; using std::setprecision; + int main(int argc, char *argv[]) { - // set dimension static const UInt dim = 3; - + // type definitions typedef Point point_type; typedef BoundingBox bbox_type; typedef SolidMechanicsModel model_type; typedef Contact > contact_type; - + initialize("steel.dat", argc, argv); - + // create mesh Mesh mesh(dim); - + // read mesh mesh.read("hertz_3D.msh"); - + // create model model_type model(mesh); SolidMechanicsModelOptions opt(_static); - + // initialize material model.initFull(opt); - + // create data structure that holds contact data contact_type cd(argc, argv, model); - + // optimal value of penalty multiplier cd[Alpha] = 0.125; cd[Multiplier_tol] = 1.e-2; cd[Newton_tol] = 1.e-2; - - // set Paraview output resluts + + // set Paraview output resluts model.setBaseName("contact"); model.addDumpFieldVector("displacement"); - + // call update current position to be able to call later // the function to get current positions model.updateCurrentPosition(); - + + // get physical names from Gmsh file mesh.createGroupsFromMeshData ("physical_names"); - + // set-up bounding box to include slave nodes that lie inside it Real l1 = 1.; Real l2 = 0.2; Real l3 = 1.; point_type c1(-l1 / 2, -l2 / 2, -l3 / 2); point_type c2(l1 / 2, l2 / 2, l3 / 2); bbox_type bb(c1, c2); - // get areas for the nodes of the circle // this is done by applying a unit pressure to the contact surface elements model.applyBC(BC::Neumann::FromHigherDim(Matrix ::eye(3, 1.)), "contact_surface"); Array & areas = model.getForce(); - + // loop over contact surface nodes and store node areas ElementGroup &eg = mesh.getElementGroup("contact_surface"); Array &coords = mesh.getNodes(); cout << "- Adding areas to slave nodes. " << endl; for (auto nit = eg.node_begin(); nit != eg.node_end(); ++nit) { - point_type p(&coords(*nit)); // ignore slave node if it doesn't lie within the bounding box if (!(bb & p)) continue; cd.addSlave(*nit); - // compute area contributing to the slave node Real a = 0.; for (UInt i = 0; i < dim; ++i) a += pow(areas(*nit, i), 2.); cd.addArea(*nit, sqrt(a)); } - + // set force value to zero areas.clear(); - + // output contact data info cout<(cd); data[0][k] = delta; data[1][k] = cd.getForce(); data[2][k] = cd.getMaxPressure(); ++k; } // print results size_t w = 14; cout << setprecision(4); cout << endl << setw(w) << "Disp." << setw(w) << "Force" << setw(w) << "Max pressure" << endl; for (size_t i = 0; i < steps; ++i) cout << setw(w) << data[0][i] << setw(w) << data[1][i] << setw(w) << data[2][i] << endl; // finalize simulation finalize(); return EXIT_SUCCESS; } diff --git a/test/test_contact/offset_1slave.cc b/test/test_contact/offset_1slave.cc index 289b57304..ebd640dfc 100644 --- a/test/test_contact/offset_1slave.cc +++ b/test/test_contact/offset_1slave.cc @@ -1,102 +1,102 @@ /** * @file offset_1slave.cc * * @author Alejandro M. Aragón * * @date Wed Jul 16 16:30:00 2014 * * @brief This file tests the basic contact implementation using the * generalized Newton method * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #include "contact_impl.hh" using namespace akantu; using std::cout; using std::endl; using std::setw; using std::setprecision; int main(int argc, char *argv[]) { // set dimension static const UInt dim = 2; // type definitions typedef SolidMechanicsModel model_type; typedef Contact > contact_type; initialize("steel.dat", argc, argv); // create meshes Mesh mesh(dim); // read meshes mesh.read("offset_1slave.msh"); // create models model_type model(mesh); SolidMechanicsModelOptions opt(_static); // initialize material // initialize material model.initFull(opt); model.updateCurrentPosition(); // create data structure that holds contact data contact_type cd(argc, argv, model); // set Paraview output resluts model.setBaseName("contact"); model.addDumpFieldVector("displacement"); mesh.createGroupsFromMeshData("physical_names"); cd.addSlave(4); cd.addArea(4, 1.0); // add master surface to find pairs cd.searchSurface("Contact"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Top"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Bottom"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_y), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _y), "Bottom"); Real U = 0.5; Real Du = 0.01; for (Real u = Du; u <= U; u += Du) { - model.applyBC(BC::Dirichlet::FixedValue(-u, BC::_y), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(-u, _y), "Top"); // solve contact step (no need to call solve on the model object) solveContactStep<_generalized_newton>(cd); } cout<<"Force: "<< cd.getForce()< * * @date Wed Jul 16 16:30:00 2014 * * @brief This file tests the basic contact implementation using the * generalized Newton method * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #include "contact_impl.hh" using namespace akantu; using std::cout; using std::endl; using std::setw; using std::setprecision; int main(int argc, char *argv[]) { // set dimension static const UInt dim = 2; // type definitions typedef SolidMechanicsModel model_type; typedef Contact > contact_type; initialize("steel.dat", argc, argv); // create meshes Mesh mesh(dim); // read meshes mesh.read("offset_2slaves.msh"); // create models model_type model(mesh); SolidMechanicsModelOptions opt(_static); // initialize material // initialize material model.initFull(opt); model.updateCurrentPosition(); // create data structure that holds contact data contact_type cd(argc, argv, model); // set Paraview output resluts model.setBaseName("contact"); model.addDumpFieldVector("displacement"); mesh.createGroupsFromMeshData("physical_names"); cd.addSlave(4); cd.addArea(4, 1.0); // add master surface to find pairs cd.searchSurface("Contact"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Top"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_x), "Bottom"); - model.applyBC(BC::Dirichlet::FixedValue(0., BC::_y), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(0., _x), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(0., _y), "Bottom"); Real U = 0.5; Real Du = 0.01; for (Real u = Du; u <= U; u += Du) { - model.applyBC(BC::Dirichlet::FixedValue(-u, BC::_y), "Top"); + model.applyBC(BC::Dirichlet::FixedValue(-u, _y), "Top"); // solve contact step (no need to call solve on the model object) solveContactStep<_generalized_newton>(cd); } cout<<"Force: "<< cd.getForce()< * * @date Wed Jun 13 11:29:49 2012 * * @brief Test for cohesive elements * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_cohesive.hh" #include "material_cohesive.hh" #include "fragment_manager.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize("material.dat",argc, argv); Math::setTolerance(1e-14); const UInt spatial_dimension = 2; const UInt max_steps = 200; Real strain_rate = 1.e5; ElementType type = _quadrangle_4; Real L = 0.03; Real theoretical_mass = L * L/20. * 2500; ElementType type_facet = Mesh::getFacetType(type); ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet); Mesh mesh(spatial_dimension); mesh.read("mesh.msh"); mesh.createGroupsFromMeshData("physical_names"); SolidMechanicsModelCohesive model(mesh); /// model initialization model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); Real time_step = model.getStableTimeStep()*0.05; model.setTimeStep(time_step); // std::cout << "Time step: " << time_step << std::endl; Real disp_increment = strain_rate * L / 2. * time_step; model.assembleMassLumped(); Array & velocity = model.getVelocity(); const Array & position = mesh.getNodes(); UInt nb_nodes = mesh.getNbNodes(); /// initial conditions for (UInt n = 0; n < nb_nodes; ++n) velocity(n, 0) = strain_rate * position(n, 0); /// boundary conditions - model.applyBC(BC::Dirichlet::FixedValue(0, BC::_x), "Left_side"); - model.applyBC(BC::Dirichlet::FixedValue(0, BC::_x), "Right_side"); + model.applyBC(BC::Dirichlet::FixedValue(0, _x), "Left_side"); + model.applyBC(BC::Dirichlet::FixedValue(0, _x), "Right_side"); model.updateResidual(); model.setBaseName("extrinsic"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("residual" ); model.addDumpField("stress"); model.addDumpField("strain"); model.dump(); UInt cohesive_index = 1; UInt nb_quad_per_facet = model.getFEEngine("FacetsFEEngine").getNbQuadraturePoints(type_facet); MaterialCohesive & mat_cohesive = dynamic_cast(model.getMaterial(cohesive_index)); const Array & damage = mat_cohesive.getDamage(type_cohesive); FragmentManager fragment_manager(model, false); const Array & fragment_mass = fragment_manager.getMass(); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { model.checkCohesiveStress(); model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); /// apply boundary conditions - model.applyBC(BC::Dirichlet::IncrementValue(-disp_increment, BC::_x), "Left_side"); - model.applyBC(BC::Dirichlet::IncrementValue( disp_increment, BC::_x), "Right_side"); + model.applyBC(BC::Dirichlet::IncrementValue(-disp_increment, _x), "Left_side"); + model.applyBC(BC::Dirichlet::IncrementValue( disp_increment, _x), "Right_side"); if(s % 1 == 0) { // model.dump(); std::cout << "passing step " << s << "/" << max_steps << std::endl; fragment_manager.computeAllData(); /// check number of fragments UInt nb_fragment_num = fragment_manager.getNbFragment(); UInt nb_cohesive_elements = mesh.getNbElement(type_cohesive); UInt nb_fragment = 1; for (UInt el = 0; el < nb_cohesive_elements; ++el) { UInt q = 0; while (q < nb_quad_per_facet && Math::are_float_equal(damage(el*nb_quad_per_facet + q), 1)) ++q; if (q == nb_quad_per_facet) { ++nb_fragment; } } if (nb_fragment != nb_fragment_num) { std::cout << "The number of fragments is wrong!" << std::endl; return EXIT_FAILURE; } /// check mass computation Real total_mass = 0.; for (UInt frag = 0; frag < nb_fragment_num; ++frag) { total_mass += fragment_mass(frag); } if (!Math::are_float_equal(theoretical_mass, total_mass)) { std::cout << "The fragments' mass is wrong!" << std::endl; return EXIT_FAILURE; } } } model.dump(); /// check velocities UInt nb_fragment = fragment_manager.getNbFragment(); const Array & fragment_velocity = fragment_manager.getVelocity(); const Array & fragment_center = fragment_manager.getCenterOfMass(); Real fragment_length = L / nb_fragment; Real initial_position = -L / 2. + fragment_length / 2.; for (UInt frag = 0; frag < nb_fragment; ++frag) { Real theoretical_center = initial_position + fragment_length * frag; if (!Math::are_float_equal(fragment_center(frag, 0), theoretical_center)) { std::cout << "The fragments' center is wrong!" << std::endl; return EXIT_FAILURE; } Real initial_vel = fragment_center(frag, 0) * strain_rate; Math::setTolerance(100); if (!Math::are_float_equal(fragment_velocity(frag), initial_vel)) { std::cout << "The fragments' velocity is wrong!" << std::endl; return EXIT_FAILURE; } } finalize(); std::cout << "OK: test_cohesive_buildfragments was passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic.cc index cf946a24f..838929d33 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic.cc @@ -1,165 +1,165 @@ /** * @file test_cohesive_extrinsic.cc * * @author Marco Vocialta * * @date Tue May 08 13:01:18 2012 * * @brief Test for cohesive elements * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_cohesive.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize("material.dat", argc, argv); debug::setDebugLevel(dblWarning); const UInt spatial_dimension = 2; const UInt max_steps = 1000; Mesh mesh(spatial_dimension); mesh.read("triangle.msh"); SolidMechanicsModelCohesive model(mesh); /// model initialization model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); - model.limitInsertion(BC::_y, -0.30, -0.20); + model.limitInsertion(_y, -0.30, -0.20); model.updateAutomaticInsertion(); Real time_step = model.getStableTimeStep()*0.05; model.setTimeStep(time_step); std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); Array & position = mesh.getNodes(); Array & velocity = model.getVelocity(); Array & boundary = model.getBlockedDOFs(); Array & displacement = model.getDisplacement(); // const Array & residual = model.getResidual(); UInt nb_nodes = mesh.getNbNodes(); /// boundary conditions for (UInt n = 0; n < nb_nodes; ++n) { if (position(n, 1) > 0.99 || position(n, 1) < -0.99) boundary(n, 1) = true; if (position(n, 0) > 0.99 || position(n, 0) < -0.99) boundary(n, 0) = true; } /// initial conditions Real loading_rate = 0.5; Real disp_update = loading_rate * time_step; for (UInt n = 0; n < nb_nodes; ++n) { velocity(n, 1) = loading_rate * position(n, 1); } model.updateResidual(); model.setBaseName("extrinsic"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("residual" ); model.addDumpFieldTensor("stress"); model.addDumpField("strain"); model.addDumpField("damage"); model.addDumpFieldToDumper("cohesive elements", "damage"); model.addDumpFieldVectorToDumper("cohesive elements", "displacement"); model.dump(); model.dump("cohesive elements"); // std::ofstream edis("edis.txt"); // std::ofstream erev("erev.txt"); // Array & residual = model.getResidual(); // const Array & stress = model.getMaterial(0).getStress(type); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { /// update displacement on extreme nodes for (UInt n = 0; n < mesh.getNbNodes(); ++n) { if (position(n, 1) > 0.99 || position(n, 1) < -0.99) displacement(n, 1) += disp_update * position(n, 1); } model.checkCohesiveStress(); model.solveStep(); if(s % 1 == 0) { model.dump(); model.dump("cohesive elements"); std::cout << "passing step " << s << "/" << max_steps << std::endl; } // Real Ed = dynamic_cast (model.getMaterial(1)).getDissipatedEnergy(); // Real Er = dynamic_cast (model.getMaterial(1)).getReversibleEnergy(); // edis << s << " " // << Ed << std::endl; // erev << s << " " // << Er << std::endl; } // edis.close(); // erev.close(); // mesh.write("mesh_final.msh"); model.dump(); Real Ed = model.getEnergy("dissipated"); Real Edt = 200 * std::sqrt(2); std::cout << Ed << " " << Edt << std::endl; if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; finalize(); return EXIT_FAILURE; } finalize(); std::cout << "OK: test_cohesive_extrinsic was passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_quadrangle.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_quadrangle.cc index 8b17e1acd..204181709 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_quadrangle.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_quadrangle.cc @@ -1,202 +1,202 @@ /** * @file test_cohesive_extrinsic_quadrangle.cc * * @author Marco Vocialta * * @date Wed Oct 03 10:20:53 2012 * * @brief Test for extrinsic cohesive elements and quadrangles * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_cohesive.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize("material.dat", argc, argv); const UInt spatial_dimension = 2; const UInt max_steps = 1000; Mesh mesh(spatial_dimension); mesh.read("quadrangle.msh"); SolidMechanicsModelCohesive model(mesh); /// model initialization model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); - model.limitInsertion(BC::_y, -0.05, 0.05); + model.limitInsertion(_y, -0.05, 0.05); model.updateAutomaticInsertion(); Real time_step = model.getStableTimeStep()*0.05; model.setTimeStep(time_step); // std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); const Array & position = mesh.getNodes(); Array & velocity = model.getVelocity(); Array & boundary = model.getBlockedDOFs(); Array & displacement = model.getDisplacement(); // const Array & residual = model.getResidual(); UInt nb_nodes = mesh.getNbNodes(); /// boundary conditions for (UInt n = 0; n < nb_nodes; ++n) { if (position(n, 1) > 0.99 || position(n, 1) < -0.99) boundary(n, 1) = true; if (position(n, 0) > 0.99 || position(n, 0) < -0.99) boundary(n, 0) = true; } model.updateResidual(); // iohelper::ElemType paraview_type = iohelper::QUAD2; // UInt nb_element = mesh.getNbElement(type); // /// initialize the paraview output // iohelper::DumperParaview dumper; // dumper.SetMode(iohelper::TEXT); // dumper.SetPoints(mesh.getNodes().storage(), // spatial_dimension, mesh.getNbNodes(), "explicit"); // dumper.SetConnectivity((int *)mesh.getConnectivity(type).storage(), // paraview_type, nb_element, iohelper::C_MODE); // dumper.AddNodeDataField(model.getDisplacement().storage(), // spatial_dimension, "displacements"); // dumper.AddNodeDataField(model.getVelocity().storage(), // spatial_dimension, "velocity"); // dumper.AddNodeDataField(model.getAcceleration().storage(), // spatial_dimension, "acceleration"); // dumper.AddNodeDataField(model.getResidual().storage(), // spatial_dimension, "forces"); // dumper.AddElemDataField(model.getMaterial(0).getStrain(type).storage(), // spatial_dimension*spatial_dimension, "strain"); // dumper.AddElemDataField(model.getMaterial(0).getStress(type).storage(), // spatial_dimension*spatial_dimension, "stress"); // dumper.SetEmbeddedValue("displacements", 1); // dumper.SetEmbeddedValue("forces", 1); // dumper.SetPrefix("paraview/"); // dumper.Init(); // dumper.Dump(); /// initial conditions Real loading_rate = 0.2; Real disp_update = loading_rate * time_step; for (UInt n = 0; n < nb_nodes; ++n) { velocity(n, 1) = loading_rate * position(n, 1); } // std::ofstream edis("edis.txt"); // std::ofstream erev("erev.txt"); // Array & residual = model.getResidual(); // const Array & stress = model.getMaterial(0).getStress(type); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { /// update displacement on extreme nodes for (UInt n = 0; n < nb_nodes; ++n) { if (position(n, 1) > 0.99 || position(n, 1) < -0.99) displacement(n, 1) += disp_update * position(n, 1); } model.checkCohesiveStress(); model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); if(s % 1 == 0) { // dumper.SetPoints(mesh.getNodes().storage(), // spatial_dimension, mesh.getNbNodes(), "explicit"); // dumper.SetConnectivity((int *)mesh.getConnectivity(type).storage(), // paraview_type, nb_element, iohelper::C_MODE); // dumper.AddNodeDataField(model.getDisplacement().storage(), // spatial_dimension, "displacements"); // dumper.AddNodeDataField(model.getVelocity().storage(), // spatial_dimension, "velocity"); // dumper.AddNodeDataField(model.getAcceleration().storage(), // spatial_dimension, "acceleration"); // dumper.AddNodeDataField(model.getResidual().storage(), // spatial_dimension, "forces"); // dumper.AddElemDataField(model.getMaterial(0).getStrain(type).storage(), // spatial_dimension*spatial_dimension, "strain"); // dumper.AddElemDataField(model.getMaterial(0).getStress(type).storage(), // spatial_dimension*spatial_dimension, "stress"); // dumper.SetEmbeddedValue("displacements", 1); // dumper.SetEmbeddedValue("forces", 1); // dumper.SetPrefix("paraview/"); // dumper.Init(); // dumper.Dump(); std::cout << "passing step " << s << "/" << max_steps << std::endl; } // Real Ed = dynamic_cast (model.getMaterial(1)).getDissipatedEnergy(); // Real Er = dynamic_cast (model.getMaterial(1)).getReversibleEnergy(); // edis << s << " " // << Ed << std::endl; // erev << s << " " // << Er << std::endl; } // edis.close(); // erev.close(); mesh.write("mesh_final.msh"); Real Ed = model.getEnergy("dissipated"); Real Edt = 200; std::cout << Ed << " " << Edt << std::endl; if (Ed < Edt * 0.99 || Ed > Edt * 1.01 || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; return EXIT_FAILURE; } finalize(); std::cout << "OK: test_cohesive_extrinsic_quadrangle was passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic.cc index 207047e1c..4c1028eeb 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic.cc @@ -1,190 +1,190 @@ /** * @file test_cohesive_intrinsic.cc * * @author Marco Vocialta * * @date Tue May 08 13:01:18 2012 * * @brief Test for cohesive elements * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" #include "material.hh" #include "dumper_paraview.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; static void updateDisplacement(SolidMechanicsModelCohesive &, Array &, ElementType, Real); int main(int argc, char *argv[]) { initialize("material.dat", argc, argv); debug::setDebugLevel(dblWarning); const UInt spatial_dimension = 2; const UInt max_steps = 350; const ElementType type = _triangle_6; Mesh mesh(spatial_dimension); mesh.read("triangle.msh"); std::cout << mesh << std::endl; SolidMechanicsModelCohesive model(mesh); /// model initialization model.initFull(); - model.limitInsertion(BC::_x, -0.26, -0.24); + model.limitInsertion(_x, -0.26, -0.24); model.insertIntrinsicElements(); mesh.write("mesh_cohesive.msh"); Real time_step = model.getStableTimeStep()*0.8; model.setTimeStep(time_step); // std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); Array & boundary = model.getBlockedDOFs(); // const Array & residual = model.getResidual(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_element = mesh.getNbElement(type); /// boundary conditions for (UInt dim = 0; dim < spatial_dimension; ++dim) { for (UInt n = 0; n < nb_nodes; ++n) { boundary(n, dim) = true; } } model.updateResidual(); model.setBaseName("intrinsic"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("residual" ); model.addDumpField("stress"); model.addDumpField("strain"); model.addDumpField("force"); model.dump(); model.setBaseNameToDumper("cohesive elements", "cohesive_elements_triangle"); model.addDumpFieldVectorToDumper("cohesive elements", "displacement"); model.addDumpFieldToDumper("cohesive elements", "damage"); model.dump("cohesive elements"); /// update displacement Array elements; Real * bary = new Real[spatial_dimension]; for (UInt el = 0; el < nb_element; ++el) { mesh.getBarycenter(el, type, bary); if (bary[0] > -0.25) elements.push_back(el); } delete[] bary; Real increment = 0.01; updateDisplacement(model, elements, type, increment); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { model.solveStep(); updateDisplacement(model, elements, type, increment); if(s % 1 == 0) { model.dump(); model.dump("cohesive elements"); std::cout << "passing step " << s << "/" << max_steps << ", Ed = " << model.getEnergy("dissipated") << std::endl; } } Real Ed = model.getEnergy("dissipated"); Real Edt = 2 * sqrt(2); std::cout << Ed << " " << Edt << std::endl; if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; return EXIT_FAILURE; } finalize(); std::cout << "OK: test_cohesive_intrinsic was passed!" << std::endl; return EXIT_SUCCESS; } static void updateDisplacement(SolidMechanicsModelCohesive & model, Array & elements, ElementType type, Real increment) { Mesh & mesh = model.getFEEngine().getMesh(); UInt nb_element = elements.getSize(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); const Array & connectivity = mesh.getConnectivity(type); Array & displacement = model.getDisplacement(); Array update(nb_nodes); update.clear(); for (UInt el = 0; el < nb_element; ++el) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity(elements(el), n); if (!update(node)) { displacement(node, 0) += increment; // displacement(node, 1) += increment; update(node) = true; } } } } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_quadrangle.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_quadrangle.cc index 72cfd46a0..4854e0243 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_quadrangle.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_quadrangle.cc @@ -1,229 +1,229 @@ /** * @file test_cohesive_intrinsic_quadrangle.cc * * @author Marco Vocialta * * @date Wed Oct 03 10:20:53 2012 * * @brief Intrinsic cohesive elements' test for quadrangles * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_cohesive.hh" #include "dumper_paraview.hh" #include "dumper_nodal_field.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; static void updateDisplacement(SolidMechanicsModelCohesive &, Array &, ElementType, Real); int main(int argc, char *argv[]) { initialize("material.dat", argc, argv); const UInt spatial_dimension = 2; const UInt max_steps = 350; const ElementType type = _quadrangle_4; Mesh mesh(spatial_dimension); mesh.read("quadrangle.msh"); // debug::setDebugLevel(dblDump); // std::cout << mesh << std::endl; // debug::setDebugLevel(dblWarning); SolidMechanicsModelCohesive model(mesh); /// model initialization model.initFull(); - model.limitInsertion(BC::_x, -0.01, 0.01); + model.limitInsertion(_x, -0.01, 0.01); model.insertIntrinsicElements(); // mesh.write("mesh_cohesive_quadrangle.msh"); // debug::setDebugLevel(dblDump); // std::cout << mesh << std::endl; // debug::setDebugLevel(dblWarning); Real time_step = model.getStableTimeStep()*0.8; model.setTimeStep(time_step); // std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); Array & boundary = model.getBlockedDOFs(); // const Array & residual = model.getResidual(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_element = mesh.getNbElement(type); /// boundary conditions for (UInt dim = 0; dim < spatial_dimension; ++dim) { for (UInt n = 0; n < nb_nodes; ++n) { boundary(n, dim) = true; } } model.updateResidual(); model.setBaseName("intrinsic_quadrangle"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("residual" ); model.addDumpField("stress"); model.addDumpField("grad_u"); model.addDumpField("force"); model.dump(); DumperParaview dumper("cohesive_elements_quadrangle"); dumper.registerMesh(mesh, spatial_dimension, _not_ghost, _ek_cohesive); dumper::NodalField * cohesive_displacement = new dumper::NodalField(model.getDisplacement()); cohesive_displacement->setPadding(3); dumper.registerField("displacement", cohesive_displacement); dumper.dump(); /// update displacement Array elements; Real * bary = new Real[spatial_dimension]; for (UInt el = 0; el < nb_element; ++el) { mesh.getBarycenter(el, type, bary); if (bary[0] > 0.) elements.push_back(el); } delete[] bary; Real increment = 0.01; updateDisplacement(model, elements, type, increment); // for (UInt n = 0; n < nb_nodes; ++n) { // if (position(n, 1) + displacement(n, 1) > 0) { // if (position(n, 0) == 0) { // displacement(n, 1) -= 0.25; // } // if (position(n, 0) == 1) { // displacement(n, 1) += 0.25; // } // } // } // std::ofstream edis("edis.txt"); // std::ofstream erev("erev.txt"); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); updateDisplacement(model, elements, type, increment); if(s % 1 == 0) { model.dump(); dumper.dump(); std::cout << "passing step " << s << "/" << max_steps << std::endl; } // // update displacement // for (UInt n = 0; n < nb_nodes; ++n) { // if (position(n, 1) + displacement(n, 1) > 0) { // displacement(n, 0) -= 0.01; // } // } // Real Ed = dynamic_cast (model.getMaterial(1)).getDissipatedEnergy(); // Real Er = dynamic_cast (model.getMaterial(1)).getReversibleEnergy(); // edis << s << " " // << Ed << std::endl; // erev << s << " " // << Er << std::endl; } // edis.close(); // erev.close(); Real Ed = model.getEnergy("dissipated"); Real Edt = 1; std::cout << Ed << " " << Edt << std::endl; if (Ed < Edt * 0.999 || Ed > Edt * 1.001) { std::cout << "The dissipated energy is incorrect" << std::endl; return EXIT_FAILURE; } finalize(); std::cout << "OK: test_cohesive_intrinsic_quadrangle was passed!" << std::endl; return EXIT_SUCCESS; } static void updateDisplacement(SolidMechanicsModelCohesive & model, Array & elements, ElementType type, Real increment) { Mesh & mesh = model.getFEEngine().getMesh(); UInt nb_element = elements.getSize(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); const Array & connectivity = mesh.getConnectivity(type); Array & displacement = model.getDisplacement(); Array update(nb_nodes); update.clear(); for (UInt el = 0; el < nb_element; ++el) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity(elements(el), n); if (!update(node)) { displacement(node, 0) += increment; // displacement(node, 1) += increment; update(node) = true; } } } } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron.cc index a3edafa27..d82938649 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron.cc @@ -1,440 +1,440 @@ /** * @file test_cohesive_intrinsic_tetrahedron.cc * * @author Marco Vocialta * * @date Tue Aug 20 14:37:18 2013 * * @brief Test for cohesive elements * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_cohesive.hh" #include "material_cohesive.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; void updateDisplacement(SolidMechanicsModelCohesive &, Array &, ElementType, Vector &); bool checkTractions(SolidMechanicsModelCohesive & model, ElementType type, Vector & opening, Vector & theoretical_traction, Matrix & rotation); void findNodesToCheck(const Mesh & mesh, const Array & elements, ElementType type, Array & nodes_to_check); bool checkEquilibrium(const Array & residual); bool checkResidual(const Array & residual, const Vector & traction, const Array & nodes_to_check, const Matrix & rotation); int main(int argc, char *argv[]) { initialize("material_tetrahedron.dat", argc, argv); // debug::setDebugLevel(dblDump); const UInt spatial_dimension = 3; const UInt max_steps = 60; const Real increment_constant = 0.01; Math::setTolerance(1.e-12); const ElementType type = _tetrahedron_10; Mesh mesh(spatial_dimension); mesh.read("tetrahedron.msh"); SolidMechanicsModelCohesive model(mesh); /// model initialization model.initFull(); - model.limitInsertion(BC::_x, -0.01, 0.01); + model.limitInsertion(_x, -0.01, 0.01); model.insertIntrinsicElements(); Array & boundary = model.getBlockedDOFs(); boundary.set(true); UInt nb_element = mesh.getNbElement(type); model.updateResidual(); model.setBaseName("intrinsic_tetrahedron"); model.addDumpFieldVector("displacement"); model.addDumpField("residual"); model.dump(); model.setBaseNameToDumper("cohesive elements", "cohesive_elements_tetrahedron"); model.addDumpFieldVectorToDumper("cohesive elements", "displacement"); model.addDumpFieldToDumper("cohesive elements", "damage"); model.dump("cohesive elements"); /// find elements to displace Array elements; Real * bary = new Real[spatial_dimension]; for (UInt el = 0; el < nb_element; ++el) { mesh.getBarycenter(el, type, bary); if (bary[0] > 0.01) elements.push_back(el); } delete[] bary; /// find nodes to check Array nodes_to_check; findNodesToCheck(mesh, elements, type, nodes_to_check); /// rotate mesh Real angle = 1.; Matrix rotation(spatial_dimension, spatial_dimension); rotation.clear(); rotation(0, 0) = std::cos(angle); rotation(0, 1) = std::sin(angle) * -1.; rotation(1, 0) = std::sin(angle); rotation(1, 1) = std::cos(angle); rotation(2, 2) = 1.; Vector increment_tmp(spatial_dimension); for (UInt dim = 0; dim < spatial_dimension; ++dim) { increment_tmp(dim) = (dim + 1) * increment_constant; } Vector increment(spatial_dimension); increment.mul(rotation, increment_tmp); Array & position = mesh.getNodes(); Array position_tmp(position); Array::iterator > position_it = position.begin(spatial_dimension); Array::iterator > position_end = position.end(spatial_dimension); Array::iterator > position_tmp_it = position_tmp.begin(spatial_dimension); for (; position_it != position_end; ++position_it, ++position_tmp_it) position_it->mul(rotation, *position_tmp_it); model.dump(); model.dump("cohesive elements"); updateDisplacement(model, elements, type, increment); Real theoretical_Ed = 0; Vector opening(spatial_dimension); Vector traction(spatial_dimension); Vector opening_old(spatial_dimension); Vector traction_old(spatial_dimension); opening.clear(); traction.clear(); opening_old.clear(); traction_old.clear(); Vector Dt(spatial_dimension); Vector Do(spatial_dimension); const Array & residual = model.getResidual(); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { model.updateResidual(); opening += increment_tmp; if (checkTractions(model, type, opening, traction, rotation) || checkEquilibrium(residual) || checkResidual(residual, traction, nodes_to_check, rotation)) { finalize(); return EXIT_FAILURE; } /// compute energy Do = opening; Do -= opening_old; Dt = traction_old; Dt += traction; theoretical_Ed += .5 * Do.dot(Dt); opening_old = opening; traction_old = traction; updateDisplacement(model, elements, type, increment); if(s % 10 == 0) { std::cout << "passing step " << s << "/" << max_steps << std::endl; model.dump(); model.dump("cohesive elements"); } } model.dump(); model.dump("cohesive elements"); Real Ed = model.getEnergy("dissipated"); theoretical_Ed *= 4.; std::cout << Ed << " " << theoretical_Ed << std::endl; if (!Math::are_float_equal(Ed, theoretical_Ed) || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; finalize(); return EXIT_FAILURE; } finalize(); std::cout << "OK: test_cohesive_intrinsic_tetrahedron was passed!" << std::endl; return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ void updateDisplacement(SolidMechanicsModelCohesive & model, Array & elements, ElementType type, Vector & increment) { UInt spatial_dimension = model.getSpatialDimension(); Mesh & mesh = model.getFEEngine().getMesh(); UInt nb_element = elements.getSize(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); const Array & connectivity = mesh.getConnectivity(type); Array & displacement = model.getDisplacement(); Array update(nb_nodes); update.clear(); for (UInt el = 0; el < nb_element; ++el) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity(elements(el), n); if (!update(node)) { Vector node_disp(displacement.storage() + node * spatial_dimension, spatial_dimension); node_disp += increment; update(node) = true; } } } } /* -------------------------------------------------------------------------- */ bool checkTractions(SolidMechanicsModelCohesive & model, ElementType type, Vector & opening, Vector & theoretical_traction, Matrix & rotation) { UInt spatial_dimension = model.getSpatialDimension(); const MaterialCohesive & mat_cohesive = dynamic_cast < const MaterialCohesive & > (model.getMaterial(1)); Real sigma_c = mat_cohesive.getParam< RandomInternalField >("sigma_c"); const Real beta = mat_cohesive.getParam("beta"); const Real G_cI = mat_cohesive.getParam("G_cI"); // Real G_cII = mat_cohesive.getParam("G_cII"); const Real delta_0 = mat_cohesive.getParam("delta_0"); const Real kappa = mat_cohesive.getParam("kappa"); Real delta_c = 2 * G_cI / sigma_c; sigma_c *= delta_c / (delta_c - delta_0); ElementType type_facet = Mesh::getFacetType(type); ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet); const Array & traction = mat_cohesive.getTraction(type_cohesive); const Array & damage = mat_cohesive.getDamage(type_cohesive); UInt nb_quad_per_el = model.getFEEngine("CohesiveFEEngine").getNbQuadraturePoints(type_cohesive); UInt nb_element = model.getMesh().getNbElement(type_cohesive); UInt tot_nb_quad = nb_element * nb_quad_per_el; Vector normal_opening(spatial_dimension); normal_opening.clear(); normal_opening(0) = opening(0); Real normal_opening_norm = normal_opening.norm(); Vector tangential_opening(spatial_dimension); tangential_opening.clear(); for (UInt dim = 1; dim < spatial_dimension; ++dim) tangential_opening(dim) = opening(dim); Real tangential_opening_norm = tangential_opening.norm(); Real beta2_kappa2 = beta * beta/kappa/kappa; Real beta2_kappa = beta * beta/kappa; Real delta = std::sqrt(tangential_opening_norm * tangential_opening_norm * beta2_kappa2 + normal_opening_norm * normal_opening_norm); delta = std::max(delta, delta_0); Real theoretical_damage = std::min(delta / delta_c, 1.); if (Math::are_float_equal(theoretical_damage, 1.)) theoretical_traction.clear(); else { theoretical_traction = tangential_opening; theoretical_traction *= beta2_kappa; theoretical_traction += normal_opening; theoretical_traction *= sigma_c / delta * (1. - theoretical_damage); } // adjust damage theoretical_damage = std::max((delta - delta_0) / (delta_c - delta_0), 0.); theoretical_damage = std::min(theoretical_damage, 1.); Vector theoretical_traction_rotated(spatial_dimension); theoretical_traction_rotated.mul(rotation, theoretical_traction); for (UInt q = 0; q < tot_nb_quad; ++q) { for (UInt dim = 0; dim < spatial_dimension; ++dim) { if (!Math::are_float_equal(theoretical_traction_rotated(dim), traction(q, dim))) { std::cout << "Tractions are incorrect" << std::endl; return 1; } } if (!Math::are_float_equal(theoretical_damage, damage(q))) { std::cout << "Damage is incorrect" << std::endl; return 1; } } return 0; } /* -------------------------------------------------------------------------- */ void findNodesToCheck(const Mesh & mesh, const Array & elements, ElementType type, Array & nodes_to_check) { const Array & connectivity = mesh.getConnectivity(type); const Array & position = mesh.getNodes(); UInt nb_nodes = position.getSize(); UInt nb_nodes_per_elem = connectivity.getNbComponent(); Array checked_nodes(nb_nodes); checked_nodes.clear(); for (UInt el = 0; el < elements.getSize(); ++el) { UInt element = elements(el); Vector conn_el(connectivity.storage() + nb_nodes_per_elem * element, nb_nodes_per_elem); for (UInt n = 0; n < nb_nodes_per_elem; ++n) { UInt node = conn_el(n); if (Math::are_float_equal(position(node, 0), 0.) && checked_nodes(node) == false) { checked_nodes(node) = true; nodes_to_check.push_back(node); } } } } /* -------------------------------------------------------------------------- */ bool checkEquilibrium(const Array & residual) { UInt spatial_dimension = residual.getNbComponent(); Vector residual_sum(spatial_dimension); residual_sum.clear(); Array::const_iterator > res_it = residual.begin(spatial_dimension); Array::const_iterator > res_end = residual.end(spatial_dimension); for (; res_it != res_end; ++res_it) residual_sum += *res_it; for (UInt s = 0; s < spatial_dimension; ++s) { if (!Math::are_float_equal(residual_sum(s), 0.)) { std::cout << "System is not in equilibrium!" << std::endl; return 1; } } return 0; } /* -------------------------------------------------------------------------- */ bool checkResidual(const Array & residual, const Vector & traction, const Array & nodes_to_check, const Matrix & rotation) { UInt spatial_dimension = residual.getNbComponent(); Vector total_force(spatial_dimension); total_force.clear(); for (UInt n = 0; n < nodes_to_check.getSize(); ++n) { UInt node = nodes_to_check(n); Vector res(residual.storage() + node * spatial_dimension, spatial_dimension); total_force += res; } Vector theoretical_total_force(spatial_dimension); theoretical_total_force.mul(rotation, traction); theoretical_total_force *= -1 * 2 * 2; for (UInt s = 0; s < spatial_dimension; ++s) { if (!Math::are_float_equal(total_force(s), theoretical_total_force(s))) { std::cout << "Total force isn't correct!" << std::endl; return 1; } } return 0; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic.cc index f026f72d9..54650ddc8 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic.cc @@ -1,184 +1,184 @@ /** * @file test_cohesive_parallel.cc * @author Marco Vocialta * @date Wed Nov 28 16:59:11 2012 * * @brief parallel test for cohesive elements * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_cohesive.hh" #include "dumper_paraview.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize("material.dat", argc, argv); const UInt max_steps = 500; UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); akantu::MeshPartition * partition = NULL; if(prank == 0) { // Read the mesh mesh.read("mesh.msh"); /// partition the mesh partition = new MeshPartitionScotch(mesh, spatial_dimension); // debug::setDebugLevel(dblDump); partition->partitionate(psize); // debug::setDebugLevel(dblWarning); } SolidMechanicsModelCohesive model(mesh); model.initParallel(partition, NULL, true); // debug::setDebugLevel(dblDump); // std::cout << mesh << std::endl; // debug::setDebugLevel(dblWarning); model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); - model.limitInsertion(BC::_y, -0.30, -0.20); + model.limitInsertion(_y, -0.30, -0.20); model.updateAutomaticInsertion(); // debug::setDebugLevel(dblDump); // std::cout << mesh_facets << std::endl; // debug::setDebugLevel(dblWarning); Real time_step = model.getStableTimeStep()*0.1; model.setTimeStep(time_step); std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); Array & position = mesh.getNodes(); Array & velocity = model.getVelocity(); Array & boundary = model.getBlockedDOFs(); Array & displacement = model.getDisplacement(); // const Array & residual = model.getResidual(); UInt nb_nodes = mesh.getNbNodes(); /// boundary conditions for (UInt n = 0; n < nb_nodes; ++n) { if (position(n, 1) > 0.99 || position(n, 1) < -0.99) boundary(n, 1) = true; if (position(n, 0) > 0.99 || position(n, 0) < -0.99) boundary(n, 0) = true; } /// initial conditions Real loading_rate = 0.5; Real disp_update = loading_rate * time_step; for (UInt n = 0; n < nb_nodes; ++n) { velocity(n, 1) = loading_rate * position(n, 1); } model.synchronizeBoundaries(); model.updateResidual(); model.setBaseName("extrinsic_parallel"); model.addDumpFieldVector("displacement"); model.addDumpFieldVector("velocity" ); model.addDumpFieldVector("acceleration"); model.addDumpFieldVector("residual" ); model.addDumpFieldTensor("stress"); model.addDumpFieldTensor("grad_u"); model.addDumpField("partitions"); // model.getDumper().getDumper().setMode(iohelper::BASE64); model.dump(); model.setBaseNameToDumper("cohesive elements", "extrinsic_parallel_cohesive_elements"); model.addDumpFieldVectorToDumper("cohesive elements", "displacement"); model.addDumpFieldToDumper("cohesive elements", "damage"); model.dump("cohesive elements"); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { /// update displacement on extreme nodes for (UInt n = 0; n < nb_nodes; ++n) { if (position(n, 1) > 0.99 || position(n, 1) < -0.99) displacement(n, 1) += disp_update * position(n, 1); } model.checkCohesiveStress(); model.solveStep(); // model.dump(); if(s % 10 == 0) { if(prank == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } // // update displacement // for (UInt n = 0; n < nb_nodes; ++n) { // if (position(n, 1) + displacement(n, 1) > 0) { // displacement(n, 0) -= 0.01; // } // } // Real Ed = dynamic_cast (model.getMaterial(1)).getDissipatedEnergy(); // Real Er = dynamic_cast (model.getMaterial(1)).getReversibleEnergy(); // edis << s << " " // << Ed << std::endl; // erev << s << " " // << Er << std::endl; } model.dump(); model.dump("cohesive elements"); // edis.close(); // erev.close(); Real Ed = model.getEnergy("dissipated"); Real Edt = 200 * sqrt(2); if(prank == 0) { std::cout << Ed << " " << Edt << std::endl; if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; finalize(); return EXIT_FAILURE; } } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic.cc index 267259095..62c99e8de 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic.cc @@ -1,165 +1,165 @@ /** * @file test_cohesive_parallel_intrinsic.cc * @author Marco Vocialta * @date Wed Nov 28 16:59:11 2012 * * @brief parallel test for intrinsic cohesive elements * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_cohesive.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize("material.dat", argc, argv); const UInt max_steps = 350; UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); akantu::MeshPartition * partition = NULL; if(prank == 0) { // Read the mesh mesh.read("mesh.msh"); // /// insert cohesive elements // CohesiveElementInserter inserter(mesh); // inserter.setLimit('x', -0.26, -0.24); // inserter.insertIntrinsicElements(); /// partition the mesh partition = new MeshPartitionScotch(mesh, spatial_dimension); // debug::setDebugLevel(dblDump); partition->partitionate(psize); // debug::setDebugLevel(dblWarning); } SolidMechanicsModelCohesive model(mesh); model.initParallel(partition); model.initFull(); - model.limitInsertion(BC::_x, -0.26, -0.24); + model.limitInsertion(_x, -0.26, -0.24); model.insertIntrinsicElements(); debug::setDebugLevel(dblDump); std::cout << mesh << std::endl; debug::setDebugLevel(dblWarning); Real time_step = model.getStableTimeStep()*0.8; model.setTimeStep(time_step); // std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); Array & position = mesh.getNodes(); Array & velocity = model.getVelocity(); Array & boundary = model.getBlockedDOFs(); // Array & displacement = model.getDisplacement(); // const Array & residual = model.getResidual(); UInt nb_nodes = mesh.getNbNodes(); Real epsilon = std::numeric_limits::epsilon(); for (UInt n = 0; n < nb_nodes; ++n) { if (std::abs(position(n, 0) - 1.) < epsilon) boundary(n, 0) = true; } model.synchronizeBoundaries(); model.updateResidual(); model.setBaseName("intrinsic_parallel"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("residual" ); model.addDumpField("stress"); model.addDumpField("strain"); model.addDumpField("partitions"); model.addDumpField("force"); model.dump(); /// initial conditions Real loading_rate = .2; for (UInt n = 0; n < nb_nodes; ++n) { velocity(n, 0) = loading_rate * position(n, 0); } /// Main loop for (UInt s = 1; s <= max_steps; ++s) { model.solveStep(); if(s % 1 == 0) { model.dump(); if(prank == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } // // update displacement // for (UInt n = 0; n < nb_nodes; ++n) { // if (position(n, 1) + displacement(n, 1) > 0) { // displacement(n, 0) -= 0.01; // } // } // Real Ed = dynamic_cast (model.getMaterial(1)).getDissipatedEnergy(); // Real Er = dynamic_cast (model.getMaterial(1)).getReversibleEnergy(); // edis << s << " " // << Ed << std::endl; // erev << s << " " // << Er << std::endl; } // edis.close(); // erev.close(); Real Ed = model.getEnergy("dissipated"); Real Edt = 2 * sqrt(2); if(prank == 0) { std::cout << Ed << " " << Edt << std::endl; if (std::abs((Ed - Edt) / Edt) > 0.01 || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; return EXIT_FAILURE; } } finalize(); if(prank == 0) std::cout << "OK: Test passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic_tetrahedron.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic_tetrahedron.cc index a4e7b5a53..be823f8a4 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic_tetrahedron.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic_tetrahedron.cc @@ -1,716 +1,716 @@ /** * @file test_cohesive_parallel_intrinsic_tetrahedron.cc * @author Marco Vocialta * @date Fri Sep 20 15:59:40 2013 * * @brief Test for 3D intrinsic cohesive elements simulation in parallel * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_cohesive.hh" #include "dumper_paraview.hh" #include "material_cohesive.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; void updateDisplacement(SolidMechanicsModelCohesive & model, const ElementTypeMapArray & elements, Vector & increment); bool checkTractions(SolidMechanicsModelCohesive & model, Vector & opening, Vector & theoretical_traction, Matrix & rotation); void findNodesToCheck(const Mesh & mesh, const ElementTypeMapArray & elements, Array & nodes_to_check, Int psize); bool checkEquilibrium(const Mesh & mesh, const Array & residual); bool checkResidual(const Array & residual, const Vector & traction, const Array & nodes_to_check, const Matrix & rotation); void findElementsToDisplace(const Mesh & mesh, ElementTypeMapArray & elements); int main(int argc, char *argv[]) { initialize("material_tetrahedron.dat", argc, argv); const UInt spatial_dimension = 3; const UInt max_steps = 60; const Real increment_constant = 0.01; ElementType type = _tetrahedron_10; Math::setTolerance(1.e-10); Mesh mesh(spatial_dimension); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); UInt nb_nodes_to_check_serial = 0; UInt total_nb_nodes = 0; UInt nb_elements_check_serial = 0; akantu::MeshPartition * partition = NULL; if(prank == 0) { // Read the mesh mesh.read("tetrahedron.msh"); /// count nodes with zero position const Array & position = mesh.getNodes(); for (UInt n = 0; n < position.getSize(); ++n) { if (std::abs(position(n, 0) - 0.) < 1e-6) ++nb_nodes_to_check_serial; } // /// insert cohesive elements // CohesiveElementInserter inserter(mesh); // inserter.setLimit(0, -0.01, 0.01); // inserter.insertIntrinsicElements(); /// find nodes to check in serial ElementTypeMapArray elements_serial("elements_serial", ""); findElementsToDisplace(mesh, elements_serial); nb_elements_check_serial = elements_serial(type).getSize(); total_nb_nodes = mesh.getNbNodes() + nb_nodes_to_check_serial; /// partition the mesh partition = new MeshPartitionScotch(mesh, spatial_dimension); debug::setDebugLevel(dblDump); partition->partitionate(psize); debug::setDebugLevel(dblInfo); } comm.broadcast(&nb_nodes_to_check_serial, 1, 0); comm.broadcast(&nb_elements_check_serial, 1, 0); SolidMechanicsModelCohesive model(mesh); model.initParallel(partition); model.initFull(); - model.limitInsertion(BC::_x, -0.01, 0.01); + model.limitInsertion(_x, -0.01, 0.01); model.insertIntrinsicElements(); { comm.broadcast(&total_nb_nodes, 1, 0); Array nb_local_nodes(psize); nb_local_nodes.clear(); for (UInt n = 0; n < mesh.getNbNodes(); ++n) { if (mesh.isLocalOrMasterNode(n)) ++nb_local_nodes(prank); } comm.allGather(nb_local_nodes.storage(), 1); UInt total_nb_nodes_parallel = std::accumulate(nb_local_nodes.begin(), nb_local_nodes.end(), 0); Array global_nodes_list(total_nb_nodes_parallel); UInt first_global_node = std::accumulate(nb_local_nodes.begin(), nb_local_nodes.begin() + prank, 0); for (UInt n = 0; n < mesh.getNbNodes(); ++n) { if (mesh.isLocalOrMasterNode(n)) { global_nodes_list(first_global_node) = mesh.getNodeGlobalId(n); ++first_global_node; } } comm.allGatherV(global_nodes_list.storage(), nb_local_nodes.storage()); if (prank == 0) std::cout << "Maximum node index: " << *(std::max_element(global_nodes_list.begin(), global_nodes_list.end())) << std::endl; Array repeated_nodes; repeated_nodes.resize(0); for (UInt n = 0; n < total_nb_nodes_parallel; ++n) { UInt appearances = std::count(global_nodes_list.begin() + n, global_nodes_list.end(), global_nodes_list(n)); if (appearances > 1) { std::cout << "Node " << global_nodes_list(n) << " appears " << appearances << " times" << std::endl; std::cout << " in position: " << n; repeated_nodes.push_back(global_nodes_list(n)); UInt * node_position = global_nodes_list.storage() + n; for (UInt i = 1; i < appearances; ++i) { node_position = std::find(node_position + 1, global_nodes_list.storage() + total_nb_nodes_parallel, global_nodes_list(n)); UInt current_index = node_position - global_nodes_list.storage(); std::cout << ", " << current_index; } std::cout << std::endl << std::endl; } } for (UInt n = 0; n < mesh.getNbNodes(); ++n) { UInt global_node = mesh.getNodeGlobalId(n); if (std::find(repeated_nodes.begin(), repeated_nodes.end(), global_node) != repeated_nodes.end()) { std::cout << "Repeated global node " << global_node << " corresponds to local node " << n << std::endl; } } if (total_nb_nodes != total_nb_nodes_parallel) { if (prank == 0) { std::cout << "Error: total number of nodes is wrong in parallel" << std::endl; std::cout << "Serial: " << total_nb_nodes << " Parallel: " << total_nb_nodes_parallel << std::endl; } finalize(); return EXIT_FAILURE; } } model.updateResidual(); model.setBaseName("intrinsic_parallel_tetrahedron"); model.addDumpFieldVector("displacement"); model.addDumpField("residual"); model.addDumpField("partitions"); model.dump(); model.setBaseNameToDumper("cohesive elements", "cohesive_elements_parallel_tetrahedron"); model.addDumpFieldVectorToDumper("cohesive elements", "displacement"); model.dump("cohesive elements"); /// find elements to displace ElementTypeMapArray elements("elements", ""); findElementsToDisplace(mesh, elements); UInt nb_elements_check = elements(type).getSize(); comm.allReduce(&nb_elements_check, 1, _so_sum); if (nb_elements_check != nb_elements_check_serial) { if (prank == 0) { std::cout << "Error: number of elements to check is wrong" << std::endl; std::cout << "Serial: " << nb_elements_check_serial << " Parallel: " << nb_elements_check << std::endl; } finalize(); return EXIT_FAILURE; } /// find nodes to check Array nodes_to_check; findNodesToCheck(mesh, elements, nodes_to_check, psize); Vector nodes_to_check_size(psize); nodes_to_check_size(prank) = nodes_to_check.getSize(); comm.allGather(nodes_to_check_size.storage(), 1); UInt nodes_to_check_global_size = std::accumulate(nodes_to_check_size.storage(), nodes_to_check_size.storage() + psize, 0); if (nodes_to_check_global_size != nb_nodes_to_check_serial) { if (prank == 0) { std::cout << "Error: number of nodes to check is wrong in parallel" << std::endl; std::cout << "Serial: " << nb_nodes_to_check_serial << " Parallel: " << nodes_to_check_global_size << std::endl; } finalize(); return EXIT_FAILURE; } /// rotate mesh Real angle = 1.; Matrix rotation(spatial_dimension, spatial_dimension); rotation.clear(); rotation(0, 0) = std::cos(angle); rotation(0, 1) = std::sin(angle) * -1.; rotation(1, 0) = std::sin(angle); rotation(1, 1) = std::cos(angle); rotation(2, 2) = 1.; Vector increment_tmp(spatial_dimension); for (UInt dim = 0; dim < spatial_dimension; ++dim) { increment_tmp(dim) = (dim + 1) * increment_constant; } Vector increment(spatial_dimension); increment.mul(rotation, increment_tmp); Array & position = mesh.getNodes(); Array position_tmp(position); Array::iterator > position_it = position.begin(spatial_dimension); Array::iterator > position_end = position.end(spatial_dimension); Array::iterator > position_tmp_it = position_tmp.begin(spatial_dimension); for (; position_it != position_end; ++position_it, ++position_tmp_it) position_it->mul(rotation, *position_tmp_it); model.dump(); model.dump("cohesive elements"); updateDisplacement(model, elements, increment); Real theoretical_Ed = 0; Vector opening(spatial_dimension); Vector traction(spatial_dimension); Vector opening_old(spatial_dimension); Vector traction_old(spatial_dimension); opening.clear(); traction.clear(); opening_old.clear(); traction_old.clear(); Vector Dt(spatial_dimension); Vector Do(spatial_dimension); const Array & residual = model.getResidual(); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { model.updateResidual(); opening += increment_tmp; if (checkTractions(model, opening, traction, rotation) || checkEquilibrium(mesh, residual) || checkResidual(residual, traction, nodes_to_check, rotation)) { finalize(); return EXIT_FAILURE; } /// compute energy Do = opening; Do -= opening_old; Dt = traction_old; Dt += traction; theoretical_Ed += .5 * Do.dot(Dt); opening_old = opening; traction_old = traction; updateDisplacement(model, elements, increment); if(s % 10 == 0) { if (prank == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; model.dump(); model.dump("cohesive elements"); } } model.dump(); model.dump("cohesive elements"); Real Ed = model.getEnergy("dissipated"); theoretical_Ed *= 4.; if (prank == 0) std::cout << "Dissipated energy: " << Ed << ", theoretical value: " << theoretical_Ed << std::endl; if (!Math::are_float_equal(Ed, theoretical_Ed) || std::isnan(Ed)) { if (prank == 0) std::cout << "Error: the dissipated energy is incorrect" << std::endl; finalize(); return EXIT_FAILURE; } finalize(); if(prank == 0) std::cout << "OK: Test passed!" << std::endl; return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ void updateDisplacement(SolidMechanicsModelCohesive & model, const ElementTypeMapArray & elements, Vector & increment) { UInt spatial_dimension = model.getSpatialDimension(); Mesh & mesh = model.getFEEngine().getMesh(); UInt nb_nodes = mesh.getNbNodes(); Array & displacement = model.getDisplacement(); Array update(nb_nodes); update.clear(); 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.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last = mesh.lastType(spatial_dimension, ghost_type); for (; it != last; ++it) { ElementType type = *it; const Array & elem = elements(type, ghost_type); const Array & connectivity = mesh.getConnectivity(type, ghost_type); UInt nb_nodes_per_element = connectivity.getNbComponent(); for (UInt el = 0; el < elem.getSize(); ++el) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity(elem(el), n); if (!update(node)) { Vector node_disp(displacement.storage() + node * spatial_dimension, spatial_dimension); node_disp += increment; update(node) = true; } } } } } } /* -------------------------------------------------------------------------- */ bool checkTractions(SolidMechanicsModelCohesive & model, Vector & opening, Vector & theoretical_traction, Matrix & rotation) { UInt spatial_dimension = model.getSpatialDimension(); const Mesh & mesh = model.getMesh(); const MaterialCohesive & mat_cohesive = dynamic_cast < const MaterialCohesive & > (model.getMaterial(1)); Real sigma_c = mat_cohesive.getParam< RandomInternalField >("sigma_c"); const Real beta = mat_cohesive.getParam("beta"); const Real G_cI = mat_cohesive.getParam("G_cI"); // Real G_cII = mat_cohesive.getParam("G_cII"); const Real delta_0 = mat_cohesive.getParam("delta_0"); const Real kappa = mat_cohesive.getParam("kappa"); Real delta_c = 2 * G_cI / sigma_c; sigma_c *= delta_c / (delta_c - delta_0); Vector normal_opening(spatial_dimension); normal_opening.clear(); normal_opening(0) = opening(0); Real normal_opening_norm = normal_opening.norm(); Vector tangential_opening(spatial_dimension); tangential_opening.clear(); for (UInt dim = 1; dim < spatial_dimension; ++dim) tangential_opening(dim) = opening(dim); Real tangential_opening_norm = tangential_opening.norm(); Real beta2_kappa2 = beta * beta/kappa/kappa; Real beta2_kappa = beta * beta/kappa; Real delta = std::sqrt(tangential_opening_norm * tangential_opening_norm * beta2_kappa2 + normal_opening_norm * normal_opening_norm); delta = std::max(delta, delta_0); Real theoretical_damage = std::min(delta / delta_c, 1.); if (Math::are_float_equal(theoretical_damage, 1.)) theoretical_traction.clear(); else { theoretical_traction = tangential_opening; theoretical_traction *= beta2_kappa; theoretical_traction += normal_opening; theoretical_traction *= sigma_c / delta * (1. - theoretical_damage); } Vector theoretical_traction_rotated(spatial_dimension); theoretical_traction_rotated.mul(rotation, theoretical_traction); // adjust damage theoretical_damage = std::max((delta - delta_0) / (delta_c - delta_0), 0.); theoretical_damage = std::min(theoretical_damage, 1.); 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.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); for (; it != last; ++it) { ElementType type = *it; const Array & traction = mat_cohesive.getTraction(type, ghost_type); const Array & damage = mat_cohesive.getDamage(type, ghost_type); UInt nb_quad_per_el = model.getFEEngine("CohesiveFEEngine").getNbQuadraturePoints(type); UInt nb_element = model.getMesh().getNbElement(type, ghost_type); UInt tot_nb_quad = nb_element * nb_quad_per_el; for (UInt q = 0; q < tot_nb_quad; ++q) { for (UInt dim = 0; dim < spatial_dimension; ++dim) { if (!Math::are_float_equal(std::abs(theoretical_traction_rotated(dim)), std::abs(traction(q, dim)))) { std::cout << "Error: tractions are incorrect" << std::endl; return 1; } } if (ghost_type == _not_ghost) if (!Math::are_float_equal(theoretical_damage, damage(q))) { std::cout << "Error: damage is incorrect" << std::endl; return 1; } } } } return 0; } /* -------------------------------------------------------------------------- */ void findNodesToCheck(const Mesh & mesh, const ElementTypeMapArray & elements, Array & nodes_to_check, Int psize) { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int prank = comm.whoAmI(); nodes_to_check.resize(0); Array global_nodes_to_check; UInt spatial_dimension = mesh.getSpatialDimension(); const Array & position = mesh.getNodes(); UInt nb_nodes = position.getSize(); Array checked_nodes(nb_nodes); checked_nodes.clear(); Mesh::type_iterator it = mesh.firstType(spatial_dimension); Mesh::type_iterator last = mesh.lastType(spatial_dimension); for (; it != last; ++it) { ElementType type = *it; const Array & elem = elements(type); const Array & connectivity = mesh.getConnectivity(type); UInt nb_nodes_per_elem = connectivity.getNbComponent(); for (UInt el = 0; el < elem.getSize(); ++el) { UInt element = elem(el); Vector conn_el(connectivity.storage() + nb_nodes_per_elem * element, nb_nodes_per_elem); for (UInt n = 0; n < nb_nodes_per_elem; ++n) { UInt node = conn_el(n); if (std::abs(position(node, 0) - 0.) < 1.e-6 && !checked_nodes(node)) { checked_nodes(node) = true; nodes_to_check.push_back(node); global_nodes_to_check.push_back(mesh.getNodeGlobalId(node)); } } } } std::vector requests; for (Int p = prank + 1; p < psize; ++p) { requests.push_back(comm.asyncSend(global_nodes_to_check.storage(), global_nodes_to_check.getSize(), p, prank)); } Array recv_nodes; for (Int p = 0; p < prank; ++p) { CommunicationStatus status; comm.probe(p, p, status); UInt recv_nodes_size = recv_nodes.getSize(); recv_nodes.resize(recv_nodes_size + status.getSize()); comm.receive(recv_nodes.storage() + recv_nodes_size, status.getSize(), p, p); } comm.waitAll(requests); comm.freeCommunicationRequest(requests); for (UInt i = 0; i < recv_nodes.getSize(); ++i) { Array::iterator node_position = std::find(global_nodes_to_check.begin(), global_nodes_to_check.end(), recv_nodes(i)); if (node_position != global_nodes_to_check.end()) { UInt index = node_position - global_nodes_to_check.begin(); nodes_to_check.erase(index); global_nodes_to_check.erase(index); } } } /* -------------------------------------------------------------------------- */ bool checkEquilibrium(const Mesh & mesh, const Array & residual) { UInt spatial_dimension = residual.getNbComponent(); Vector residual_sum(spatial_dimension); residual_sum.clear(); Array::const_iterator > res_it = residual.begin(spatial_dimension); for (UInt n = 0; n < residual.getSize(); ++n, ++res_it) { if (mesh.isLocalOrMasterNode(n)) residual_sum += *res_it; } StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); comm.allReduce(residual_sum.storage(), spatial_dimension, _so_sum); for (UInt s = 0; s < spatial_dimension; ++s) { if (!Math::are_float_equal(residual_sum(s), 0.)) { if (comm.whoAmI() == 0) std::cout << "Error: system is not in equilibrium!" << std::endl; return 1; } } return 0; } /* -------------------------------------------------------------------------- */ bool checkResidual(const Array & residual, const Vector & traction, const Array & nodes_to_check, const Matrix & rotation) { UInt spatial_dimension = residual.getNbComponent(); Vector total_force(spatial_dimension); total_force.clear(); for (UInt n = 0; n < nodes_to_check.getSize(); ++n) { UInt node = nodes_to_check(n); Vector res(residual.storage() + node * spatial_dimension, spatial_dimension); total_force += res; } StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); comm.allReduce(total_force.storage(), spatial_dimension, _so_sum); Vector theoretical_total_force(spatial_dimension); theoretical_total_force.mul(rotation, traction); theoretical_total_force *= -1 * 2 * 2; for (UInt s = 0; s < spatial_dimension; ++s) { if (!Math::are_float_equal(total_force(s), theoretical_total_force(s))) { if (comm.whoAmI() == 0) std::cout << "Error: total force isn't correct!" << std::endl; return 1; } } return 0; } /* -------------------------------------------------------------------------- */ void findElementsToDisplace(const Mesh & mesh, ElementTypeMapArray & elements) { UInt spatial_dimension = mesh.getSpatialDimension(); mesh.initElementTypeMapArray(elements, 1, spatial_dimension); Vector bary(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.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last = mesh.lastType(spatial_dimension, ghost_type); for (; it != last; ++it) { ElementType type = *it; Array & elem = elements(type, ghost_type); UInt nb_element = mesh.getNbElement(type, ghost_type); for (UInt el = 0; el < nb_element; ++el) { mesh.getBarycenter(el, type, bary.storage(), ghost_type); if (bary(0) > 0.0001) elem.push_back(el); } } } } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc index 2c73e41f6..251f869fa 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc @@ -1,87 +1,87 @@ /** * @file test_local_material.cc * * @author Guillaume Anciaux * @author Marion Estelle Chambart * * @date Fri Nov 26 00:17:56 2010 * * @brief test of the class SolidMechanicsModel * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" #include "local_material_damage.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { akantu::initialize("material.dat", argc, argv); UInt max_steps = 200; Real epot, ekin; const UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); mesh.read("barre_trou.msh"); mesh.createGroupsFromMeshData("physical_names"); SolidMechanicsModel model(mesh); /// model initialization model.initFull(SolidMechanicsModelOptions(_explicit_lumped_mass, true)); model.registerNewCustomMaterials("local_damage"); model.initMaterials(); Real time_step = model.getStableTimeStep(); model.setTimeStep(time_step/10.); model.assembleMassLumped(); std::cout << model << std::endl; /// Dirichlet boundary conditions - model.applyBC(BC::Dirichlet::FixedValue(0.0, BC::_x), "Fixed"); - model.applyBC(BC::Dirichlet::FixedValue(0.0, BC::_y), "Fixed"); + model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "Fixed"); + model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "Fixed"); // Boundary condition (Neumann) Matrix stress(2,2); stress.eye(3e6); model.applyBC(BC::Neumann::FromHigherDim(stress), "Traction"); for(UInt s = 0; s < max_steps; ++s) { model.solveStep(); epot = model.getPotentialEnergy(); ekin = model.getKineticEnergy(); std::cout << s << " " << epot << " " << ekin << " " << epot + ekin << std::endl; } akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc index 181573d1b..543b5f684 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc @@ -1,96 +1,95 @@ /** - * @file test_solid_mechanics_model_square.cc - * - * @author Nicolas Richart + * @file test_material_thermal.cc + + * @author Lucas Frerot * - * @date Wed Sep 22 13:39:02 2010 + * @date Thu 11 21 13:48:26 2013 * - * @brief test of the class SolidMechanicsModel + * @brief test of the class akantu::MaterialThermal * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; -int main(int argc, char *argv[]) -{ +int main(int argc, char *argv[]) { debug::setDebugLevel(dblWarning); initialize("material_thermal.dat", argc, argv); Math::setTolerance(1.e-13); Mesh mesh(2); mesh.read("square.msh"); SolidMechanicsModel model(mesh); model.initFull(SolidMechanicsModelOptions(_static)); mesh.computeBoundingBox(); const Vector & min = mesh.getLowerBounds(); const Vector & max = mesh.getUpperBounds(); Array & pos = mesh.getNodes(); Array & boundary = model.getBlockedDOFs(); Array & disp = model.getDisplacement(); for (UInt i = 0; i < mesh.getNbNodes(); ++i) { if (Math::are_float_equal(pos(i, 0), min(0))) { boundary(i, 0) = true; } if (Math::are_float_equal(pos(i, 1), min(1))) { boundary(i, 1) = true; } } model.setBaseName("test_material_thermal"); model.addDumpField("displacement"); model.addDumpField("strain"); model.addDumpField("stress"); model.addDumpField("delta_T"); model.solveStatic<_scm_newton_raphson_tangent_modified, _scc_increment>(1e-10, 2); for (UInt i = 0; i < mesh.getNbNodes(); ++i) { if (Math::are_float_equal(pos(i, 0), max(0)) && Math::are_float_equal(pos(i, 1), max(1))) { if (!Math::are_float_equal(disp(i, 0), 1.0) || !Math::are_float_equal(disp(i, 1), 1.0)) { AKANTU_DEBUG_ERROR("Test not passed"); return EXIT_FAILURE; } } } model.dump(); finalize(); std::cout << "Test passed" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_boundary_condition.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_boundary_condition.cc index d779a6f89..7df9c892a 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_boundary_condition.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_boundary_condition.cc @@ -1,59 +1,59 @@ #include #include #include "aka_common.hh" #include "aka_error.hh" #include "mesh.hh" #include "solid_mechanics_model.hh" #include "boundary_condition_functor.hh" using namespace akantu; /* -------------------------------------------------------------------------- */ int main(int argc, char* argv[]) { UInt spatial_dimension(3); akantu::initialize("material.dat", argc, argv); Mesh mesh(spatial_dimension, "mesh_names"); std::cout << "Loading the mesh." << std::endl; mesh.read("./cube_physical_names.msh"); mesh.createGroupsFromMeshData("physical_names"); std::stringstream sstr; SolidMechanicsModel model(mesh); model.initFull(); std::cout << model.getMaterial(0) << std::endl; Vector surface_traction(3); surface_traction(0)=0.0; surface_traction(1)=0.0; surface_traction(2)=-1.0; Matrix surface_stress(3, 3, 0.0); surface_stress(0,0)=0.0; surface_stress(1,1)=0.0; surface_stress(2,2)=-1.0; - model.applyBC(BC::Dirichlet::FixedValue(13.0, BC::_x), "Bottom"); - model.applyBC(BC::Dirichlet::FixedValue(13.0, BC::_y), "Bottom"); - model.applyBC(BC::Dirichlet::FixedValue(13.0, BC::_z), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(13.0, _x), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(13.0, _y), "Bottom"); + model.applyBC(BC::Dirichlet::FixedValue(13.0, _z), "Bottom"); //model.applyBC(BC::Neumann::FromSameDim(surface_traction), "Top"); model.applyBC(BC::Neumann::FromHigherDim(surface_stress), "Top"); debug::setDebugLevel(dblTest); std::cout << model.getDisplacement(); std::cout << model.getForce(); debug::setDebugLevel(dblInfo); akantu::finalize(); return EXIT_SUCCESS; }