Page MenuHomec4science

solid_mechanics_model_cohesive.cc
No OneTemporary

File Metadata

Created
Sun, Sep 15, 20:18

solid_mechanics_model_cohesive.cc

/**
* @file solid_mechanics_model_cohesive.cc
* @author Marco Vocialta <marco.vocialta@epfl.ch>
* @date Thu Apr 19 10:42:11 2012
*
* @brief Solid mechanics model 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 <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
__BEGIN_AKANTU__
/* -------------------------------------------------------------------------- */
SolidMechanicsModelCohesive::SolidMechanicsModelCohesive(Mesh & mesh,
UInt dim,
const ID & id,
const MemoryID & memory_id)
: SolidMechanicsModel(mesh, dim, id, memory_id),
mesh_facets(mesh.getSpatialDimension(),
mesh.getNodes().getID(),
id, memory_id) {
AKANTU_DEBUG_IN();
registerFEMObject<MyFEMCohesiveType>("CohesiveFEM", mesh, spatial_dimension);
MeshUtils::buildAllFacets(mesh, mesh_facets);
/// assign cohesive type
Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1);
Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1);
for (; it != last; ++it) {
const Vector<UInt> & connectivity = mesh_facets.getConnectivity(*it);
if (connectivity.getSize() != 0) {
type_facet = *it;
break;
}
}
if (type_facet == _segment_2) type_cohesive = _cohesive_2d_4;
else if (type_facet == _segment_3) type_cohesive = _cohesive_2d_6;
mesh.addConnectivityType(type_cohesive);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::initFull(std::string material_file,
AnalysisMethod method) {
SolidMechanicsModel::initFull(material_file, method);
if(material_file != "") {
initCohesiveMaterial();
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::initCohesiveMaterial() {
AKANTU_DEBUG_IN();
/// find the cohesive index
cohesive_index = 0;
MaterialCohesive * mat_cohesive;
while ((mat_cohesive =
dynamic_cast<MaterialCohesive *>(materials[cohesive_index])) == NULL
&& cohesive_index <= materials.size())
++cohesive_index;
AKANTU_DEBUG_ASSERT(cohesive_index != materials.size(),
"No cohesive materials in the material input file");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* Initialize the model,basically it pre-compute the shapes, shapes derivatives
* and jacobian
*
*/
void SolidMechanicsModelCohesive::initModel() {
SolidMechanicsModel::initModel();
getFEM("CohesiveFEM").initShapeFunctions(_not_ghost);
getFEM("CohesiveFEM").initShapeFunctions(_ghost);
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::initExtrinsic(std::string material_file,
AnalysisMethod method) {
AKANTU_DEBUG_IN();
SolidMechanicsModelCohesive::initFull(material_file, method);
MaterialCohesiveLinearExtrinsic * mat_cohesive
= dynamic_cast<MaterialCohesiveLinearExtrinsic*>(materials[cohesive_index]);
AKANTU_DEBUG_ASSERT(mat_cohesive, "Choose the linear extrinsic cohesive constitutive law");
UInt nb_facet = mesh_facets.getNbElement(type_facet);
sigma_lim.resize(nb_facet);
const Real sigma_c = mat_cohesive->getSigmaC();
const Real rand = mat_cohesive->getRandFactor();
std::srand(time(NULL));
for (UInt f = 0; f < nb_facet; ++f)
sigma_lim(f) = sigma_c * (1 + std::rand()/(Real)RAND_MAX * rand);
registerFEMObject<MyFEMType>("FacetsFEM", mesh_facets, spatial_dimension-1);
getFEM("FacetsFEM").initShapeFunctions();
getFEM("FacetsFEM").computeNormalsOnControlPoints();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::checkCohesiveStress() {
AKANTU_DEBUG_IN();
UInt nb_facet = mesh_facets.getNbElement(type_facet);
UInt nb_quad_facet = getFEM("FacetsFEM").getNbQuadraturePoints(type_facet);
Vector<UInt> facet_insertion;
Vector<Real> sigma_insertion;
const Vector<Real> & normals = getFEM("FacetsFEM").getNormalsOnQuadPoints(type_facet);
const Vector<Vector<Element> > & element_to_facet
= mesh_facets.getElementToSubelement(type_facet);
for (UInt f = 0; f < nb_facet; ++f) {
/// check that facet isn't on the boundary
if (element_to_facet(f)(1).type != _not_defined) {
Vector<Real> stress_on_quad(2*nb_quad_facet, spatial_dimension);
for (UInt el = 0; el < 2; ++el) {
UInt elem_nb = element_to_facet(f)(el).element;
ElementType type_elem = element_to_facet(f)(el).type;
// UInt nb_quad_elem = getFEM().getNbQuadraturePoints(type_elem);
const Vector<Real> & stress = getMaterial(0).getStress(type_elem);
/// linear element case
types::Matrix stress_local(spatial_dimension, spatial_dimension);
for (UInt i = 0; i < spatial_dimension; ++i)
for (UInt j = 0; j < spatial_dimension; ++j)
stress_local(i, j) = stress(elem_nb, i*spatial_dimension + j);
types::RVector normal(spatial_dimension);
for (UInt i = 0; i < spatial_dimension; ++i)
normal(i) = normals(f, i);
types::RVector stress_norm(spatial_dimension);
stress_norm.mul<false>(stress_local, normal);
for (UInt dim = 0; dim < spatial_dimension; ++dim)
stress_on_quad(el, dim) = fabs(stress_norm(dim));
}
Real sigma_max = *std::max_element(stress_on_quad.storage(),
stress_on_quad.storage() +
stress_on_quad.getSize() *
stress_on_quad.getNbComponent());
if (sigma_lim(f) < sigma_max) {
facet_insertion.push_back(f);
sigma_insertion.push_back(sigma_max);
}
}
}
insertCohesiveElements(facet_insertion, true);
/// resize cohesive material vectors
MaterialCohesiveLinearExtrinsic * mat_cohesive
= dynamic_cast<MaterialCohesiveLinearExtrinsic*>(materials[cohesive_index]);
AKANTU_DEBUG_ASSERT(mat_cohesive, "Initialize the material with initExtrinsic");
mat_cohesive->resizeCohesiveVectors(sigma_insertion);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::insertCohesiveElements(const Vector<UInt> & facet_insertion,
const bool random_sigma) {
AKANTU_DEBUG_IN();
Vector<UInt> doubled_nodes(0, 2);
Vector<UInt> doubled_facets(0, 2);
/// update mesh
for (UInt f = 0; f < facet_insertion.getSize(); ++f) {
Element facet;
facet.element = facet_insertion(f);
facet.type = type_facet;
doubleFacet(facet, doubled_nodes, doubled_facets);
}
/// double middle nodes if it's the case
if (type_facet == _segment_3) {
doubleMiddleNode(doubled_nodes, doubled_facets);
}
/// update nodal values
updateDoubledNodes(doubled_nodes);
/// loop over doubled facets to insert cohesive elements
Vector<UInt> & conn_cohesive = mesh.getConnectivity(type_cohesive);
const Vector<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet);
UInt nb_nodes_per_facet = conn_facet.getNbComponent();
const Vector<Real> & position = mesh.getNodes();
Vector<UInt> & element_mat = getElementMaterial(type_cohesive);
for (UInt f = 0; f < doubled_facets.getSize(); ++f) {
UInt nb_cohesive_elements = conn_cohesive.getSize();
conn_cohesive.resize(nb_cohesive_elements + 1);
UInt first_facet = doubled_facets(f, 0);
UInt second_facet = doubled_facets(f, 1);
/// copy first facet's connectivity
for (UInt n = 0; n < nb_nodes_per_facet; ++n)
conn_cohesive(nb_cohesive_elements, n) = conn_facet(first_facet, n);
/// check if first nodes of the two facets are coincident or not
UInt first_facet_node = conn_facet(first_facet, 0);
UInt second_facet_node = conn_facet(second_facet, 0);
bool second_facet_inversion = false;
for (UInt dim = 0; dim < mesh.getSpatialDimension(); ++dim) {
if (position(first_facet_node, dim) != position(second_facet_node, dim)) {
second_facet_inversion = true;
break;
}
}
/// if the two nodes are coincident second facet connectivity is
/// normally copied, otherwise the copy is reverted
if (!second_facet_inversion) {
for (UInt n = 0; n < nb_nodes_per_facet; ++n)
conn_cohesive(nb_cohesive_elements, n + nb_nodes_per_facet)
= conn_facet(second_facet, n);
}
else {
for (UInt n = 0; n < nb_nodes_per_facet; ++n)
conn_cohesive(nb_cohesive_elements, n + nb_nodes_per_facet)
= conn_facet(second_facet, nb_nodes_per_facet - n - 1);
}
/// assign the cohesive material to the new element
element_mat.resize(nb_cohesive_elements + 1);
element_mat(nb_cohesive_elements) = cohesive_index;
materials[cohesive_index]->addElement(type_cohesive, nb_cohesive_elements, _not_ghost);
}
/// update shape functions
getFEM("CohesiveFEM").initShapeFunctions(_not_ghost);
/// resize cohesive material vectors
if (!random_sigma) {
MaterialCohesive * mat_cohesive
= dynamic_cast<MaterialCohesive*>(materials[cohesive_index]);
AKANTU_DEBUG_ASSERT(mat_cohesive, "No cohesive materials in the materials vector");
mat_cohesive->resizeCohesiveVectors();
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::doubleMiddleNode(Vector<UInt> & doubled_nodes, const Vector<UInt> & doubled_facets) {
AKANTU_DEBUG_IN();
Vector<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet);
Vector<Real> & position = mesh.getNodes();
Vector<Vector<Element> > & elem_to_facet
= mesh_facets.getElementToSubelement(type_facet);
for (UInt f = 0; f < doubled_facets.getSize(); ++f) {
UInt facet_first = doubled_facets(f, 0);
UInt facet_second = doubled_facets(f, 1);
UInt new_node = position.getSize();
/// store doubled nodes
UInt nb_doubled_nodes = doubled_nodes.getSize();
doubled_nodes.resize(nb_doubled_nodes + 1);
UInt old_node = conn_facet(facet_first, 2);
doubled_nodes(nb_doubled_nodes, 0) = old_node;
doubled_nodes(nb_doubled_nodes, 1) = new_node;
/// update position
position.resize(new_node + 1);
for (UInt dim = 0; dim < spatial_dimension; ++dim)
position(new_node, dim) = position(old_node, dim);
/// update facet connectivity
conn_facet(facet_second, 2) = new_node;
/// update element connectivity
for (UInt el = 0; el < elem_to_facet(facet_second).getSize(); ++el) {
const ElementType type_elem = elem_to_facet(facet_second)(el).type;
if (type_elem != _not_defined) {
UInt elem_global = elem_to_facet(facet_second)(el).element;
Vector<UInt> & conn_elem = mesh.getConnectivity(type_elem);
for (UInt n = 0; n < conn_elem.getNbComponent(); ++n) {
if (conn_elem(elem_global, n) == old_node)
conn_elem(elem_global, n) = new_node;
}
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::updateDoubledNodes(const Vector<UInt> & doubled_nodes) {
AKANTU_DEBUG_IN();
UInt nb_old_nodes = displacement->getSize();
UInt nb_new_nodes = nb_old_nodes + doubled_nodes.getSize();
displacement ->resize(nb_new_nodes);
velocity ->resize(nb_new_nodes);
acceleration ->resize(nb_new_nodes);
increment_acceleration->resize(nb_new_nodes);
force ->resize(nb_new_nodes);
residual ->resize(nb_new_nodes);
boundary ->resize(nb_new_nodes);
mass ->resize(nb_new_nodes);
/**
* @todo temporary patch, should be done in a better way that works
* always (pbc, parallel, ...)
**/
delete dof_synchronizer;
dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension);
dof_synchronizer->initLocalDOFEquationNumbers();
dof_synchronizer->initGlobalDOFEquationNumbers();
for (UInt n = 0; n < doubled_nodes.getSize(); ++n) {
UInt old_node = doubled_nodes(n, 0);
UInt new_node = doubled_nodes(n, 1);
for (UInt dim = 0; dim < displacement->getNbComponent(); ++dim) {
(*displacement)(new_node, dim) = (*displacement)(old_node, dim);
}
for (UInt dim = 0; dim < velocity->getNbComponent(); ++dim) {
(*velocity)(new_node, dim) = (*velocity)(old_node, dim);
}
for (UInt dim = 0; dim < acceleration->getNbComponent(); ++dim) {
(*acceleration)(new_node, dim) = (*acceleration)(old_node, dim);
}
for (UInt dim = 0; dim < increment_acceleration->getNbComponent(); ++dim) {
(*increment_acceleration)(new_node, dim)
= (*increment_acceleration)(old_node, dim);
}
}
assembleMassLumped();
updateCurrentPosition();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::doubleFacet(Element & facet,
Vector<UInt> & doubled_nodes,
Vector<UInt> & doubled_facets) {
AKANTU_DEBUG_IN();
const UInt f_index = facet.element;
const ElementType type_facet = facet.type;
const ElementType type_subfacet = mesh.getFacetElementType(type_facet);
const UInt nb_subfacet = mesh.getNbFacetsPerElement(type_facet);
Vector<Vector<Element> > & facet_to_subfacet
= mesh_facets.getElementToSubelement(type_subfacet);
Vector<Vector<Element> > & element_to_facet
= mesh_facets.getElementToSubelement(type_facet);
Vector<Element> & subfacet_to_facet
= mesh_facets.getSubelementToElement(type_facet);
/// adding a new facet by copying original one
/// create new connectivity
Vector<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet);
UInt nb_facet = conn_facet.getSize();
conn_facet.resize(nb_facet + 1);
for (UInt n = 0; n < conn_facet.getNbComponent(); ++n)
conn_facet(nb_facet, n) = conn_facet(f_index, n);
/// store doubled facets
UInt nb_doubled_facets = doubled_facets.getSize();
doubled_facets.resize(nb_doubled_facets + 1);
doubled_facets(nb_doubled_facets, 0) = f_index;
doubled_facets(nb_doubled_facets, 1) = nb_facet;
/// update elements connected to facet
element_to_facet.push_back(element_to_facet(f_index));
/// set new and original facets as boundary facets
element_to_facet(f_index)(1) = ElementNull;
element_to_facet(nb_facet)(0) = element_to_facet(nb_facet)(1);
element_to_facet(nb_facet)(1) = ElementNull;
/// update facet_to_element vector
ElementType type = element_to_facet(nb_facet)(0).type;
UInt el = element_to_facet(nb_facet)(0).element;
Vector<Element> & facet_to_element = mesh_facets.getSubelementToElement(type);
UInt i;
for (i = 0; facet_to_element(el, i).element != f_index
&& i <= facet_to_element.getNbComponent(); ++i);
facet_to_element(el, i).element = nb_facet;
/// create new links to subfacets and update list of facets
/// connected to subfacets
subfacet_to_facet.resize(nb_facet + 1);
for (UInt sf = 0; sf < nb_subfacet; ++sf) {
subfacet_to_facet(nb_facet, sf) = subfacet_to_facet(f_index, sf);
UInt sf_index = subfacet_to_facet(f_index, sf).element;
/// find index to start looping around facets connected to current
/// subfacet
UInt start = 0;
UInt nb_connected_facets = facet_to_subfacet(sf_index).getSize();
while (facet_to_subfacet(sf_index)(start).element != f_index
&& start <= facet_to_subfacet(sf_index).getSize()) ++start;
/// add the new facet to the list next to the original one
++nb_connected_facets;
facet_to_subfacet(sf_index).resize(nb_connected_facets);
for (UInt f = nb_connected_facets - 1; f > start; --f) {
facet_to_subfacet(sf_index)(f) = facet_to_subfacet(sf_index)(f - 1);
}
/// check if the new facet should be inserted before or after the
/// original one: the second element connected to both original
/// and new facet will be _not_defined, so I check if the first
/// one is equal to one of the elements connected to the following
/// facet in the facet_to_subfacet vector
UInt f_start = facet_to_subfacet(sf_index)(start).element;
UInt f_next;
if (start + 2 == nb_connected_facets)
f_next = facet_to_subfacet(sf_index)(0).element;
else
f_next = facet_to_subfacet(sf_index)(start + 2).element;
if ((element_to_facet(f_start)(0) == element_to_facet(f_next)(0))
|| ( element_to_facet(f_start)(0) == element_to_facet(f_next)(1)))
facet_to_subfacet(sf_index)(start).element = nb_facet;
else
facet_to_subfacet(sf_index)(start + 1).element = nb_facet;
/// loop on every facet connected to the current subfacet
for (UInt f = start + 2; ; ++f) {
/// reset f in order to continue looping from the beginning
if (f == nb_connected_facets) f = 0;
/// exit loop if it reaches the end
if (f == start) break;
/// if current loop facet is on the boundary, double subfacet
UInt f_global = facet_to_subfacet(sf_index)(f).element;
if (element_to_facet(f_global)(1).type == _not_defined) {
doubleSubfacet(subfacet_to_facet(f_index, sf), start, f, doubled_nodes);
break;
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::doubleSubfacet(const Element & subfacet,
UInt start,
UInt end,
Vector<UInt> & doubled_nodes) {
AKANTU_DEBUG_IN();
const UInt sf_index = subfacet.element;
const ElementType type_subfacet = subfacet.type;
Vector<Vector<Element> > & facet_to_subfacet
= mesh_facets.getElementToSubelement(type_subfacet);
UInt nb_subfacet = facet_to_subfacet.getSize();
Vector<UInt> & conn_point = mesh_facets.getConnectivity(_point);
Vector<Real> & position = mesh.getNodes();
/// add the new subfacet
if (spatial_dimension == 2) {
UInt new_node = position.getSize();
/// add new node in connectivity
UInt new_subfacet = conn_point.getSize();
conn_point.resize(new_subfacet + 1);
conn_point(new_subfacet) = new_node;
/// store doubled nodes
UInt nb_doubled_nodes = doubled_nodes.getSize();
doubled_nodes.resize(nb_doubled_nodes + 1);
UInt old_node = doubled_nodes(nb_doubled_nodes, 0)
= conn_point(sf_index);
doubled_nodes(nb_doubled_nodes, 1) = new_node;
/// update position
position.resize(new_node + 1);
for (UInt dim = 0; dim < spatial_dimension; ++dim)
position(new_node, dim) = position(old_node, dim);
}
/// create a vector for the new subfacet in facet_to_subfacet
facet_to_subfacet.resize(nb_subfacet + 1);
UInt nb_connected_facets = facet_to_subfacet(sf_index).getSize();
/// loop over facets from start to end
for (UInt f = start + 1; ; ++f) {
/// reset f in order to continue looping from the beginning
if (f == nb_connected_facets) f = 0;
UInt f_global = facet_to_subfacet(sf_index)(f).element;
ElementType type_facet = facet_to_subfacet(sf_index)(f).type;
Vector<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet);
UInt old_node = conn_point(sf_index);
UInt new_node = conn_point(conn_point.getSize() - 1);
/// update facet connectivity
UInt i;
for (i = 0; conn_facet(f_global, i) != old_node
&& i <= conn_facet.getNbComponent(); ++i);
conn_facet(f_global, i) = new_node;
/// update element connectivity
Vector<Vector<Element> > & elem_to_facet
= mesh_facets.getElementToSubelement(type_facet);
for (UInt el = 0; el < elem_to_facet(f_global).getSize(); ++el) {
const ElementType type_elem = elem_to_facet(f_global)(el).type;
if (type_elem != _not_defined) {
UInt elem_global = elem_to_facet(f_global)(el).element;
Vector<UInt> & conn_elem = mesh.getConnectivity(type_elem);
for (UInt n = 0; n < conn_elem.getNbComponent(); ++n) {
if (conn_elem(elem_global, n) == old_node)
conn_elem(elem_global, n) = new_node;
}
}
}
/// update subfacet_to_facet vector
Vector<Element> & subfacet_to_facet
= mesh_facets.getSubelementToElement(type_facet);
for (i = 0; subfacet_to_facet(f_global, i).element != sf_index
&& i <= subfacet_to_facet.getNbComponent(); ++i);
subfacet_to_facet(f_global, i).element = nb_subfacet;
/// add current facet to facet_to_subfacet last position
Element current_facet;
current_facet.element = f_global;
current_facet.type = type_facet;
facet_to_subfacet(nb_subfacet).push_back(current_facet);
/// exit loop if it reaches the end
if (f == end) break;
}
/// rearrange the facets connected to the original subfacet and
/// compute the new number of facets connected to it
if (end < start) {
for (UInt f = 0; f < start - end; ++f)
facet_to_subfacet(sf_index)(f) = facet_to_subfacet(sf_index)(f + end + 1);
nb_connected_facets = start - end;
}
else {
for (UInt f = 1; f < nb_connected_facets - end; ++f)
facet_to_subfacet(sf_index)(start + f) = facet_to_subfacet(sf_index)(end + f);
nb_connected_facets -= end - start;
}
/// resize list of facets of the original subfacet
facet_to_subfacet(sf_index).resize(nb_connected_facets);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::printself(std::ostream & stream, int indent) const {
std::string space;
for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
stream << space << "SolidMechanicsModelCohesive [" << std::endl;
SolidMechanicsModel::printself(stream, indent + 1);
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
__END_AKANTU__

Event Timeline