Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F90817968
mesh_utils.cc
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Nov 5, 01:20
Size
72 KB
Mime Type
text/x-c
Expires
Thu, Nov 7, 01:20 (2 d)
Engine
blob
Format
Raw Data
Handle
22138778
Attached To
rAKA akantu
mesh_utils.cc
View Options
/**
* @file mesh_utils.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Leonardo Snozzi <leonardo.snozzi@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
* @author Dana Christen <dana.christen@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Aug 20 2010
* @date last modification: Mon Jun 09 2014
*
* @brief All mesh utils necessary for various tasks
*
* @section LICENSE
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_utils.hh"
#include "aka_safe_enum.hh"
#include "fe_engine.hh"
/* -------------------------------------------------------------------------- */
#include <limits>
#include <numeric>
#include <queue>
#include <set>
/* -------------------------------------------------------------------------- */
__BEGIN_AKANTU__
/* -------------------------------------------------------------------------- */
void MeshUtils::buildNode2Elements(const Mesh & mesh,
CSR<Element> & node_to_elem,
UInt spatial_dimension) {
AKANTU_DEBUG_IN();
if (spatial_dimension == _all_dimensions) spatial_dimension = mesh.getSpatialDimension();
/// count number of occurrence of each node
UInt nb_nodes = mesh.getNbNodes();
/// array for the node-element list
node_to_elem.resizeRows(nb_nodes);
node_to_elem.clearRows();
AKANTU_DEBUG_ASSERT(mesh.firstType(spatial_dimension) !=
mesh.lastType(spatial_dimension),
"Some elements must be found in right dimension to compute facets!");
for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) {
Mesh::type_iterator first = mesh.firstType(spatial_dimension, *gt, _ek_not_defined);
Mesh::type_iterator last = mesh.lastType(spatial_dimension, *gt, _ek_not_defined);
for (; first != last; ++first) {
ElementType type = *first;
UInt nb_element = mesh.getNbElement(type, *gt);
Array<UInt>::const_iterator< Vector<UInt> > conn_it =
mesh.getConnectivity(type, *gt).begin(Mesh::getNbNodesPerElement(type));
for (UInt el = 0; el < nb_element; ++el, ++conn_it)
for (UInt n = 0; n < conn_it->size(); ++n)
++node_to_elem.rowOffset((*conn_it)(n));
}
}
node_to_elem.countToCSR();
node_to_elem.resizeCols();
/// rearrange element to get the node-element list
Element e;
node_to_elem.beginInsertions();
for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) {
Mesh::type_iterator first = mesh.firstType(spatial_dimension, *gt, _ek_not_defined);
Mesh::type_iterator last = mesh.lastType(spatial_dimension, *gt, _ek_not_defined);
e.ghost_type = *gt;
for (; first != last; ++first) {
ElementType type = *first;
e.type = type;
e.kind = Mesh::getKind(type);
UInt nb_element = mesh.getNbElement(type, *gt);
Array<UInt>::const_iterator< Vector<UInt> > conn_it =
mesh.getConnectivity(type, *gt).begin(Mesh::getNbNodesPerElement(type));
for (UInt el = 0; el < nb_element; ++el, ++conn_it) {
e.element = el;
for (UInt n = 0; n < conn_it->size(); ++n)
node_to_elem.insertInRow((*conn_it)(n), e);
}
}
}
node_to_elem.endInsertions();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* This function should disappear in the future (used in mesh partitioning)
*/
void MeshUtils::buildNode2Elements(const Mesh & mesh,
CSR<UInt> & node_to_elem,
UInt spatial_dimension) {
AKANTU_DEBUG_IN();
if (spatial_dimension == _all_dimensions) spatial_dimension = mesh.getSpatialDimension();
UInt nb_nodes = mesh.getNbNodes();
const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList();
Mesh::ConnectivityTypeList::const_iterator it;
UInt nb_types = type_list.size();
UInt nb_good_types = 0;
UInt nb_nodes_per_element[nb_types];
UInt * conn_val[nb_types];
UInt nb_element[nb_types];
for(it = type_list.begin(); it != type_list.end(); ++it) {
ElementType type = *it;
if(Mesh::getSpatialDimension(type) != spatial_dimension) continue;
nb_nodes_per_element[nb_good_types] = Mesh::getNbNodesPerElement(type);
conn_val[nb_good_types] = mesh.getConnectivity(type, _not_ghost).storage();
nb_element[nb_good_types] = mesh.getConnectivity(type, _not_ghost).getSize();
nb_good_types++;
}
AKANTU_DEBUG_ASSERT(nb_good_types != 0,
"Some elements must be found in right dimension to compute facets!");
/// array for the node-element list
node_to_elem.resizeRows(nb_nodes);
node_to_elem.clearRows();
/// count number of occurrence of each node
for (UInt t = 0; t < nb_good_types; ++t) {
for (UInt el = 0; el < nb_element[t]; ++el) {
UInt el_offset = el*nb_nodes_per_element[t];
for (UInt n = 0; n < nb_nodes_per_element[t]; ++n) {
++node_to_elem.rowOffset(conn_val[t][el_offset + n]);
}
}
}
node_to_elem.countToCSR();
node_to_elem.resizeCols();
node_to_elem.beginInsertions();
/// rearrange element to get the node-element list
for (UInt t = 0, linearized_el = 0; t < nb_good_types; ++t)
for (UInt el = 0; el < nb_element[t]; ++el, ++linearized_el) {
UInt el_offset = el*nb_nodes_per_element[t];
for (UInt n = 0; n < nb_nodes_per_element[t]; ++n)
node_to_elem.insertInRow(conn_val[t][el_offset + n], linearized_el);
}
node_to_elem.endInsertions();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::buildNode2ElementsElementTypeMap(const Mesh & mesh,
CSR<UInt> & node_to_elem,
const ElementType & type,
const GhostType & ghost_type) {
AKANTU_DEBUG_IN();
UInt nb_nodes = mesh.getNbNodes();
UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
UInt nb_elements = mesh.getConnectivity(type, ghost_type).getSize();
UInt * conn_val = mesh.getConnectivity(type, ghost_type).storage();
/// array for the node-element list
node_to_elem.resizeRows(nb_nodes);
node_to_elem.clearRows();
/// count number of occurrence of each node
for (UInt el = 0; el < nb_elements; ++el) {
UInt el_offset = el*nb_nodes_per_element;
for (UInt n = 0; n < nb_nodes_per_element; ++n)
++node_to_elem.rowOffset(conn_val[el_offset + n]);
}
/// convert the occurrence array in a csr one
node_to_elem.countToCSR();
node_to_elem.resizeCols();
node_to_elem.beginInsertions();
/// save the element index in the node-element list
for (UInt el = 0; el < nb_elements; ++el) {
UInt el_offset = el*nb_nodes_per_element;
for (UInt n = 0; n < nb_nodes_per_element; ++n) {
node_to_elem.insertInRow(conn_val[el_offset + n], el);
}
}
node_to_elem.endInsertions();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::buildFacets(Mesh & mesh){
AKANTU_DEBUG_IN();
UInt spatial_dimension = mesh.getSpatialDimension();
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType gt_facet = *gt;
Mesh::type_iterator it = mesh.firstType(spatial_dimension - 1, gt_facet);
Mesh::type_iterator end = mesh.lastType(spatial_dimension - 1, gt_facet);
for(; it != end; ++it) {
mesh.getConnectivity(*it, *gt).resize(0);
// \todo inform the mesh event handler
}
}
buildFacetsDimension(mesh,
mesh,
true,
spatial_dimension);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::buildAllFacets(const Mesh & mesh,
Mesh & mesh_facets,
UInt to_dimension,
DistributedSynchronizer * synchronizer) {
AKANTU_DEBUG_IN();
UInt spatial_dimension = mesh.getSpatialDimension();
buildAllFacets(mesh, mesh_facets, spatial_dimension, to_dimension, synchronizer);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::buildAllFacets(const Mesh & mesh,
Mesh & mesh_facets,
UInt from_dimension,
UInt to_dimension,
DistributedSynchronizer * synchronizer) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_ASSERT(mesh_facets.isMeshFacets(),
"The mesh_facets should be initialized with initMeshFacets");
const ElementTypeMapArray<UInt> * prank_to_element = NULL;
if (synchronizer) {
synchronizer->buildPrankToElement();
prank_to_element = &synchronizer->getPrankToElement();
}
/// generate facets
buildFacetsDimension(mesh,
mesh_facets,
false,
from_dimension,
prank_to_element);
/// copy nodes type
mesh_facets.nodes_type.resize(mesh.nodes_type.getSize());
mesh_facets.nodes_type.copy(mesh.nodes_type);
/// sort facets and generate subfacets
for (UInt i = from_dimension - 1; i > to_dimension; --i) {
buildFacetsDimension(mesh_facets,
mesh_facets,
false,
i,
prank_to_element);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::buildFacetsDimension(const Mesh & mesh,
Mesh & mesh_facets,
bool boundary_only,
UInt dimension,
const ElementTypeMapArray<UInt> * prank_to_element){
AKANTU_DEBUG_IN();
// save the current parent of mesh_facets and set it temporarly to mesh since
// mesh is the one containing the elements for which mesh_facets has the subelements
// example: if the function is called with mesh = mesh_facets
const Mesh & mesh_facets_parent = mesh_facets.getMeshParent();
mesh_facets.defineMeshParent(mesh);
UInt spatial_dimension = mesh.getSpatialDimension();
const Array<Real> & mesh_facets_nodes = mesh_facets.getNodes();
const Array<Real>::const_vector_iterator mesh_facets_nodes_it =
mesh_facets_nodes.begin(spatial_dimension);
CSR<Element> node_to_elem;
buildNode2Elements(mesh, node_to_elem, dimension);
Array<UInt> counter;
std::vector<Element> connected_elements;
// init the SubelementToElement data to improve performance
for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) {
GhostType ghost_type = *gt;
Mesh::type_iterator first = mesh.firstType(dimension, ghost_type);
Mesh::type_iterator last = mesh.lastType(dimension, ghost_type);
for(; first != last; ++first) {
ElementType type = *first;
mesh_facets.getSubelementToElementPointer(type, ghost_type);
Vector<ElementType> facet_types = mesh.getAllFacetTypes(type);
for (UInt ft = 0; ft < facet_types.size(); ++ft) {
ElementType facet_type = facet_types(ft);
mesh_facets.getElementToSubelementPointer(facet_type, ghost_type);
mesh_facets.getConnectivityPointer(facet_type, ghost_type);
}
}
}
Element current_element;
for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) {
GhostType ghost_type = *gt;
GhostType facet_ghost_type = ghost_type;
current_element.ghost_type = ghost_type;
Mesh::type_iterator first = mesh.firstType(dimension, ghost_type);
Mesh::type_iterator last = mesh.lastType(dimension, ghost_type);
for(; first != last; ++first) {
ElementType type = *first;
Vector<ElementType> facet_types = mesh.getAllFacetTypes(type);
current_element.type = type;
for (UInt ft = 0; ft < facet_types.size(); ++ft) {
ElementType facet_type = facet_types(ft);
UInt nb_element = mesh.getNbElement(type, ghost_type);
Array< std::vector<Element> > * element_to_subelement =
&mesh_facets.getElementToSubelement(facet_type, ghost_type);
Array<UInt> * connectivity_facets = &mesh_facets.getConnectivity(facet_type, ghost_type);
UInt nb_facet_per_element = mesh.getNbFacetsPerElement(type, ft);
const Array<UInt> & element_connectivity = mesh.getConnectivity(type, ghost_type);
const Matrix<UInt> facet_local_connectivity = mesh.getFacetLocalConnectivity(type, ft);
UInt nb_nodes_per_facet = connectivity_facets->getNbComponent();
Vector<UInt> facet(nb_nodes_per_facet);
for (UInt el = 0; el < nb_element; ++el) {
current_element.element = el;
for (UInt f = 0; f < nb_facet_per_element; ++f) {
for (UInt n = 0; n < nb_nodes_per_facet; ++n)
facet(n) = element_connectivity(el, facet_local_connectivity(f, n));
UInt first_node_nb_elements = node_to_elem.getNbCols(facet(0));
counter.resize(first_node_nb_elements);
counter.clear();
//loop over the other nodes to search intersecting elements,
//which are the elements that share another node with the
//starting element after first_node
CSR<Element>::iterator first_node_elements = node_to_elem.begin(facet(0));
CSR<Element>::iterator first_node_elements_end = node_to_elem.end(facet(0));
UInt local_el = 0;
for (; first_node_elements != first_node_elements_end;
++first_node_elements, ++local_el) {
for (UInt n = 1; n < nb_nodes_per_facet; ++n) {
CSR<Element>::iterator node_elements_begin = node_to_elem.begin(facet(n));
CSR<Element>::iterator node_elements_end = node_to_elem.end (facet(n));
counter(local_el) += std::count(node_elements_begin,
node_elements_end,
*first_node_elements);
}
}
// counting the number of elements connected to the facets and
// taking the minimum element number, because the facet should
// be inserted just once
UInt nb_element_connected_to_facet = 0;
Element minimum_el = ElementNull;
connected_elements.clear();
for (UInt el_f = 0; el_f < first_node_nb_elements; el_f++) {
Element real_el = node_to_elem(facet(0), el_f);
if (counter(el_f) == nb_nodes_per_facet - 1) {
++nb_element_connected_to_facet;
minimum_el = std::min(minimum_el, real_el);
connected_elements.push_back(real_el);
}
}
if (minimum_el == current_element) {
bool full_ghost_facet = false;
UInt n = 0;
while (n < nb_nodes_per_facet && mesh.isPureGhostNode(facet(n))) ++n;
if (n == nb_nodes_per_facet) full_ghost_facet = true;
if (!full_ghost_facet) {
if (!boundary_only || (boundary_only && nb_element_connected_to_facet == 1)) {
std::vector<Element> elements;
// build elements_on_facets: linearized_el must come first
// in order to store the facet in the correct direction
// and avoid to invert the sign in the normal computation
elements.push_back(current_element);
/// boundary facet
if (nb_element_connected_to_facet == 1)
elements.push_back(ElementNull);
/// internal facet
else if (nb_element_connected_to_facet == 2) {
elements.push_back(connected_elements[1]);
/// check if facet is in between ghost and normal
/// elements: if it's the case, the facet is either
/// ghost or not ghost. The criterion to decide this
/// is arbitrary. It was chosen to check the processor
/// id (prank) of the two neighboring elements. If
/// prank of the ghost element is lower than prank of
/// the normal one, the facet is not ghost, otherwise
/// it's ghost
GhostType gt[2] = { _not_ghost, _not_ghost };
for (UInt el = 0; el < connected_elements.size(); ++el)
gt[el] = connected_elements[el].ghost_type;
if (gt[0] + gt[1] == 1) {
if (prank_to_element) {
UInt prank[2];
for (UInt el = 0; el < 2; ++el) {
UInt current_el = connected_elements[el].element;
ElementType current_type = connected_elements[el].type;
GhostType current_gt = connected_elements[el].ghost_type;
const Array<UInt> & prank_to_el
= (*prank_to_element)(current_type, current_gt);
prank[el] = prank_to_el(current_el);
}
bool ghost_one = (gt[0] != _ghost);
if (prank[ghost_one] > prank[!ghost_one])
facet_ghost_type = _not_ghost;
else
facet_ghost_type = _ghost;
connectivity_facets = &mesh_facets.getConnectivity(facet_type, facet_ghost_type);
element_to_subelement = &mesh_facets.getElementToSubelement(facet_type, facet_ghost_type);
}
}
}
/// facet of facet
else {
for (UInt i = 1; i < nb_element_connected_to_facet; ++i) {
elements.push_back(connected_elements[i]);
}
}
element_to_subelement->push_back(elements);
connectivity_facets->push_back(facet);
/// current facet index
UInt current_facet = connectivity_facets->getSize() - 1;
/// loop on every element connected to current facet and
/// insert current facet in the first free spot of the
/// subelement_to_element vector
for (UInt elem = 0; elem < elements.size(); ++elem) {
Element loc_el = elements[elem];
if (loc_el.type != _not_defined) {
Array<Element> & subelement_to_element =
mesh_facets.getSubelementToElement(loc_el.type, loc_el.ghost_type);
UInt nb_facet_per_loc_element = subelement_to_element.getNbComponent();
for (UInt f_in = 0; f_in < nb_facet_per_loc_element; ++f_in) {
if (subelement_to_element(loc_el.element, f_in).type == _not_defined) {
subelement_to_element(loc_el.element, f_in).type = facet_type;
subelement_to_element(loc_el.element, f_in).element = current_facet;
subelement_to_element(loc_el.element, f_in).ghost_type = facet_ghost_type;
break;
}
}
}
}
/// reset connectivity in case a facet was found in
/// between ghost and normal elements
if (facet_ghost_type != ghost_type) {
facet_ghost_type = ghost_type;
connectivity_facets = mesh_facets.getConnectivityPointer(facet_type, facet_ghost_type);
element_to_subelement = mesh_facets.getElementToSubelementPointer(facet_type, facet_ghost_type);
}
}
}
}
}
}
}
}
}
// restore the parent of mesh_facet
mesh_facets.defineMeshParent(mesh_facets_parent);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::renumberMeshNodes(Mesh & mesh,
UInt * local_connectivities,
UInt nb_local_element,
UInt nb_ghost_element,
ElementType type,
Array<UInt> & old_nodes_numbers) {
AKANTU_DEBUG_IN();
UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
std::map<UInt, UInt> renumbering_map;
for (UInt i = 0; i < old_nodes_numbers.getSize(); ++i) {
renumbering_map[old_nodes_numbers(i)] = i;
}
/// renumber the nodes
renumberNodesInConnectivity(local_connectivities,
(nb_local_element + nb_ghost_element)*nb_nodes_per_element,
renumbering_map);
std::map<UInt, UInt>::iterator it = renumbering_map.begin();
std::map<UInt, UInt>::iterator end = renumbering_map.end();
old_nodes_numbers.resize(renumbering_map.size());
for (;it != end; ++it) {
old_nodes_numbers(it->second) = it->first;
}
renumbering_map.clear();
/// copy the renumbered connectivity to the right place
Array<UInt> * local_conn = mesh.getConnectivityPointer(type);
local_conn->resize(nb_local_element);
memcpy(local_conn->storage(),
local_connectivities,
nb_local_element * nb_nodes_per_element * sizeof(UInt));
Array<UInt> * ghost_conn = mesh.getConnectivityPointer(type, _ghost);
ghost_conn->resize(nb_ghost_element);
memcpy(ghost_conn->storage(),
local_connectivities + nb_local_element * nb_nodes_per_element,
nb_ghost_element * nb_nodes_per_element * sizeof(UInt));
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::renumberNodesInConnectivity(UInt * list_nodes,
UInt nb_nodes,
std::map<UInt, UInt> & renumbering_map) {
AKANTU_DEBUG_IN();
UInt * connectivity = list_nodes;
UInt new_node_num = renumbering_map.size();
for (UInt n = 0; n < nb_nodes; ++n, ++connectivity) {
UInt & node = *connectivity;
std::map<UInt, UInt>::iterator it = renumbering_map.find(node);
if(it == renumbering_map.end()) {
UInt old_node = node;
renumbering_map[old_node] = new_node_num;
node = new_node_num;
++new_node_num;
} else {
node = it->second;
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::purifyMesh(Mesh & mesh) {
AKANTU_DEBUG_IN();
std::map<UInt, UInt> renumbering_map;
RemovedNodesEvent remove_nodes(mesh);
Array<UInt> & nodes_removed = remove_nodes.getList();
for (UInt gt = _not_ghost; gt <= _ghost; ++gt) {
GhostType ghost_type = (GhostType) gt;
Mesh::type_iterator it = mesh.firstType(_all_dimensions, ghost_type, _ek_not_defined);
Mesh::type_iterator end = mesh.lastType(_all_dimensions, ghost_type, _ek_not_defined);
for(; it != end; ++it) {
ElementType type(*it);
UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
const Array<UInt> & connectivity_vect = mesh.getConnectivity(type, ghost_type);
UInt nb_element(connectivity_vect.getSize());
UInt * connectivity = connectivity_vect.storage();
renumberNodesInConnectivity (connectivity, nb_element*nb_nodes_per_element, renumbering_map);
}
}
Array<UInt> & new_numbering = remove_nodes.getNewNumbering();
std::fill(new_numbering.begin(), new_numbering.end(), UInt(-1));
std::map<UInt, UInt>::iterator it = renumbering_map.begin();
std::map<UInt, UInt>::iterator end = renumbering_map.end();
for (; it != end; ++it) {
new_numbering(it->first) = it->second;
}
for (UInt i = 0; i < new_numbering.getSize(); ++i) {
if(new_numbering(i) == UInt(-1))
nodes_removed.push_back(i);
}
mesh.sendEvent(remove_nodes);
AKANTU_DEBUG_OUT();
}
#if defined(AKANTU_COHESIVE_ELEMENT)
/* -------------------------------------------------------------------------- */
UInt MeshUtils::insertCohesiveElements(Mesh & mesh,
Mesh & mesh_facets,
const ElementTypeMapArray<bool> & facet_insertion,
Array<UInt> & doubled_nodes,
Array<Element> & new_elements,
bool only_double_facets) {
UInt spatial_dimension = mesh.getSpatialDimension();
UInt elements_to_insert = updateFacetToDouble(mesh_facets, facet_insertion);
if (elements_to_insert > 0) {
if (spatial_dimension == 1) {
doublePointFacet(mesh, mesh_facets, doubled_nodes);
}
else {
doubleFacet(mesh, mesh_facets, spatial_dimension - 1,
doubled_nodes, true);
findSubfacetToDouble<false>(mesh, mesh_facets);
if (spatial_dimension == 2) {
doubleSubfacet<2>(mesh, mesh_facets, doubled_nodes);
}
else if (spatial_dimension == 3) {
doubleFacet(mesh, mesh_facets, 1, doubled_nodes, false);
findSubfacetToDouble<true>(mesh, mesh_facets);
doubleSubfacet<3>(mesh, mesh_facets, doubled_nodes);
}
}
if (!only_double_facets)
updateCohesiveData(mesh, mesh_facets, new_elements);
}
return elements_to_insert;
}
#endif
/* -------------------------------------------------------------------------- */
void MeshUtils::doubleNodes(Mesh & mesh,
const std::vector<UInt> & old_nodes,
Array<UInt> & doubled_nodes) {
AKANTU_DEBUG_IN();
Array<Real> & position = mesh.getNodes();
UInt spatial_dimension = mesh.getSpatialDimension();
UInt old_nb_nodes = position.getSize();
UInt new_nb_nodes = old_nb_nodes + old_nodes.size();
UInt old_nb_doubled_nodes = doubled_nodes.getSize();
UInt new_nb_doubled_nodes = old_nb_doubled_nodes + old_nodes.size();
position.resize(new_nb_nodes);
doubled_nodes.resize(new_nb_doubled_nodes);
Array<Real>::iterator<Vector<Real> > position_begin
= position.begin(spatial_dimension);
for (UInt n = 0; n < old_nodes.size(); ++n) {
UInt new_node = old_nb_nodes + n;
/// store doubled nodes
doubled_nodes(old_nb_doubled_nodes + n, 0) = old_nodes[n];
doubled_nodes(old_nb_doubled_nodes + n, 1) = new_node;
/// update position
std::copy(position_begin + old_nodes[n],
position_begin + old_nodes[n] + 1,
position_begin + new_node);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::doubleFacet(Mesh & mesh,
Mesh & mesh_facets,
UInt facet_dimension,
Array<UInt> & doubled_nodes,
bool facet_mode) {
AKANTU_DEBUG_IN();
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType gt_facet = *gt;
Mesh::type_iterator it = mesh_facets.firstType(facet_dimension, gt_facet);
Mesh::type_iterator end = mesh_facets.lastType(facet_dimension, gt_facet);
for(; it != end; ++it) {
ElementType type_facet = *it;
Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double",
type_facet,
gt_facet);
UInt nb_facet_to_double = f_to_double.getSize();
if (nb_facet_to_double == 0) continue;
ElementType type_subfacet = Mesh::getFacetType(type_facet);
const UInt nb_subfacet_per_facet = Mesh::getNbFacetsPerElement(type_facet);
GhostType gt_subfacet = _casper;
Array<std::vector<Element> > * f_to_subfacet = NULL;
Array<Element> & subfacet_to_facet
= mesh_facets.getSubelementToElement(type_facet, gt_facet);
Array<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet);
UInt nb_nodes_per_facet = conn_facet.getNbComponent();
UInt old_nb_facet = conn_facet.getSize();
UInt new_nb_facet = old_nb_facet + nb_facet_to_double;
conn_facet.resize(new_nb_facet);
subfacet_to_facet.resize(new_nb_facet);
UInt new_facet = old_nb_facet - 1;
Element new_facet_el(type_facet, 0, gt_facet);
Array<Element>::iterator<Vector<Element> > subfacet_to_facet_begin
= subfacet_to_facet.begin(nb_subfacet_per_facet);
Array<UInt>::iterator<Vector<UInt> > conn_facet_begin
= conn_facet.begin(nb_nodes_per_facet);
for (UInt facet = 0; facet < nb_facet_to_double; ++facet) {
UInt old_facet = f_to_double(facet);
++new_facet;
/// adding a new facet by copying original one
/// copy connectivity in new facet
std::copy(conn_facet_begin + old_facet,
conn_facet_begin + old_facet + 1,
conn_facet_begin + new_facet);
/// update subfacet_to_facet
std::copy(subfacet_to_facet_begin + old_facet,
subfacet_to_facet_begin + old_facet + 1,
subfacet_to_facet_begin + new_facet);
new_facet_el.element = new_facet;
/// loop on every subfacet
for (UInt sf = 0; sf < nb_subfacet_per_facet; ++sf) {
Element & subfacet = subfacet_to_facet(old_facet, sf);
if (subfacet == ElementNull) continue;
if (gt_subfacet != subfacet.ghost_type) {
gt_subfacet = subfacet.ghost_type;
f_to_subfacet = & mesh_facets.getElementToSubelement(type_subfacet,
subfacet.ghost_type);
}
/// update facet_to_subfacet array
(*f_to_subfacet)(subfacet.element).push_back(new_facet_el);
}
}
/// update facet_to_subfacet and _segment_3 facets if any
if (!facet_mode) {
updateSubfacetToFacet(mesh_facets, type_facet, gt_facet, true);
updateFacetToSubfacet(mesh_facets, type_facet, gt_facet, true);
updateQuadraticSegments<true>(mesh, mesh_facets, type_facet,
gt_facet, doubled_nodes);
}
else
updateQuadraticSegments<false>(mesh, mesh_facets, type_facet,
gt_facet, doubled_nodes);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
UInt MeshUtils::updateFacetToDouble(Mesh & mesh_facets,
const ElementTypeMapArray<bool> & facet_insertion) {
AKANTU_DEBUG_IN();
UInt spatial_dimension = mesh_facets.getSpatialDimension();
UInt nb_facets_to_double = 0.;
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType gt_facet = *gt;
Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet);
Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet);
for(; it != end; ++it) {
ElementType type_facet = *it;
const Array<bool> & f_insertion = facet_insertion(type_facet, gt_facet);
Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double",
type_facet,
gt_facet);
Array< std::vector<Element> > & element_to_facet
= mesh_facets.getElementToSubelement(type_facet, gt_facet);
ElementType el_type = _not_defined;
GhostType el_gt = _casper;
UInt nb_facet_per_element = 0;
Element old_facet_el(type_facet, 0, gt_facet);
Array<Element> * facet_to_element = NULL;
for (UInt f = 0; f < f_insertion.getSize(); ++f) {
if (f_insertion(f) == false) continue;
++nb_facets_to_double;
if (element_to_facet(f)[1].type == _not_defined
#if defined(AKANTU_COHESIVE_ELEMENT)
|| element_to_facet(f)[1].kind == _ek_cohesive
#endif
) {
AKANTU_DEBUG_WARNING("attempt to double a facet on the boundary");
continue;
}
f_to_double.push_back(f);
UInt new_facet =
mesh_facets.getNbElement(type_facet, gt_facet) + f_to_double.getSize() - 1;
old_facet_el.element = f;
/// update facet_to_element vector
Element & elem_to_update = element_to_facet(f)[1];
UInt el = elem_to_update.element;
if (elem_to_update.ghost_type != el_gt || elem_to_update.type != el_type) {
el_type = elem_to_update.type;
el_gt = elem_to_update.ghost_type;
facet_to_element = & mesh_facets.getSubelementToElement(el_type, el_gt);
nb_facet_per_element = facet_to_element->getNbComponent();
}
Element * f_update
= std::find(facet_to_element->storage() + el * nb_facet_per_element,
facet_to_element->storage() + el * nb_facet_per_element
+ nb_facet_per_element,
old_facet_el);
AKANTU_DEBUG_ASSERT(facet_to_element->storage() + el * nb_facet_per_element !=
facet_to_element->storage() + el * nb_facet_per_element
+ nb_facet_per_element,
"Facet not found");
f_update->element = new_facet;
/// update elements connected to facet
std::vector<Element> first_facet_list = element_to_facet(f);
element_to_facet.push_back(first_facet_list);
/// set new and original facets as boundary facets
element_to_facet(new_facet)[0] = element_to_facet(new_facet)[1];
element_to_facet(f)[1] = ElementNull;
element_to_facet(new_facet)[1] = ElementNull;
}
}
}
AKANTU_DEBUG_OUT();
return nb_facets_to_double;
}
/* -------------------------------------------------------------------------- */
void MeshUtils::resetFacetToDouble(Mesh & mesh_facets) {
AKANTU_DEBUG_IN();
for(UInt g = _not_ghost; g <= _ghost; ++g) {
GhostType gt = (GhostType) g;
Mesh::type_iterator it = mesh_facets.firstType(_all_dimensions, gt);
Mesh::type_iterator end = mesh_facets.lastType(_all_dimensions, gt);
for(; it != end; ++it) {
ElementType type = *it;
mesh_facets.getDataPointer<UInt>("facet_to_double", type, gt, 1, false);
mesh_facets.getDataPointer<std::vector<Element> >
("facets_to_subfacet_double", type, gt, 1, false);
mesh_facets.getDataPointer<std::vector<Element> >
("elements_to_subfacet_double", type, gt, 1, false);
mesh_facets.getDataPointer<std::vector<Element> >
("subfacets_to_subsubfacet_double", type, gt, 1, false);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <bool subsubfacet_mode>
void MeshUtils::findSubfacetToDouble(Mesh & mesh, Mesh & mesh_facets) {
AKANTU_DEBUG_IN();
UInt spatial_dimension = mesh_facets.getSpatialDimension();
if (spatial_dimension == 1) return;
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType gt_facet = *gt;
Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet);
Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet);
for(; it != end; ++it) {
ElementType type_facet = *it;
Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double",
type_facet,
gt_facet);
UInt nb_facet_to_double = f_to_double.getSize();
if (nb_facet_to_double == 0) continue;
ElementType type_subfacet = Mesh::getFacetType(type_facet);
GhostType gt_subfacet = _casper;
ElementType type_subsubfacet = Mesh::getFacetType(type_subfacet);
GhostType gt_subsubfacet = _casper;
Array<UInt> * conn_subfacet = NULL;
Array<UInt> * sf_to_double = NULL;
Array<std::vector<Element> > * sf_to_subfacet_double = NULL;
Array<std::vector<Element> > * f_to_subfacet_double = NULL;
Array<std::vector<Element> > * el_to_subfacet_double = NULL;
UInt nb_subfacet = Mesh::getNbFacetsPerElement(type_facet);
UInt nb_subsubfacet;
UInt nb_nodes_per_sf_el;
if (subsubfacet_mode) {
nb_nodes_per_sf_el = Mesh::getNbNodesPerElement(type_subsubfacet);
nb_subsubfacet = Mesh::getNbFacetsPerElement(type_subfacet);
}
else
nb_nodes_per_sf_el = Mesh::getNbNodesPerElement(type_subfacet);
Array<Element> & subfacet_to_facet
= mesh_facets.getSubelementToElement(type_facet, gt_facet);
Array< std::vector<Element> > & element_to_facet
= mesh_facets.getElementToSubelement(type_facet, gt_facet);
Array<Element> * subsubfacet_to_subfacet = NULL;
UInt old_nb_facet = subfacet_to_facet.getSize() - nb_facet_to_double;
Element current_facet(type_facet, 0, gt_facet);
std::vector<Element> element_list;
std::vector<Element> facet_list;
std::vector<Element> * subfacet_list;
if (subsubfacet_mode)
subfacet_list = new std::vector<Element>;
/// map to filter subfacets
Array< std::vector<Element> > * facet_to_subfacet = NULL;
/// this is used to make sure that both new and old facets are
/// checked
UInt facets[2];
/// loop on every facet
for (UInt f_index = 0; f_index < 2; ++f_index) {
for (UInt facet = 0; facet < nb_facet_to_double; ++facet) {
facets[bool(f_index)] = f_to_double(facet);
facets[!bool(f_index)] = old_nb_facet + facet;
UInt old_facet = facets[0];
UInt new_facet = facets[1];
Element & starting_element = element_to_facet(new_facet)[0];
current_facet.element = old_facet;
/// loop on every subfacet
for (UInt sf = 0; sf < nb_subfacet; ++sf) {
Element & subfacet = subfacet_to_facet(old_facet, sf);
if (subfacet == ElementNull) continue;
if (gt_subfacet != subfacet.ghost_type) {
gt_subfacet = subfacet.ghost_type;
if (subsubfacet_mode) {
subsubfacet_to_subfacet
= & mesh_facets.getSubelementToElement(type_subfacet,
gt_subfacet);
}
else {
conn_subfacet = & mesh_facets.getConnectivity(type_subfacet,
gt_subfacet);
sf_to_double = & mesh_facets.getData<UInt>("facet_to_double",
type_subfacet,
gt_subfacet);
f_to_subfacet_double
= & mesh_facets.getData<std::vector<Element> >("facets_to_subfacet_double",
type_subfacet,
gt_subfacet);
el_to_subfacet_double
= & mesh_facets.getData<std::vector<Element> >("elements_to_subfacet_double",
type_subfacet,
gt_subfacet);
facet_to_subfacet
= & mesh_facets.getElementToSubelement(type_subfacet,
gt_subfacet);
}
}
if (subsubfacet_mode) {
/// loop on every subsubfacet
for (UInt ssf = 0; ssf < nb_subsubfacet; ++ssf) {
Element & subsubfacet
= (*subsubfacet_to_subfacet)(subfacet.element, ssf);
if (subsubfacet == ElementNull) continue;
if (gt_subsubfacet != subsubfacet.ghost_type) {
gt_subsubfacet = subsubfacet.ghost_type;
conn_subfacet = & mesh_facets.getConnectivity(type_subsubfacet,
gt_subsubfacet);
sf_to_double = & mesh_facets.getData<UInt>("facet_to_double",
type_subsubfacet,
gt_subsubfacet);
sf_to_subfacet_double
= & mesh_facets.getData<std::vector<Element> >("subfacets_to_subsubfacet_double",
type_subsubfacet,
gt_subsubfacet);
f_to_subfacet_double
= & mesh_facets.getData<std::vector<Element> >("facets_to_subfacet_double",
type_subsubfacet,
gt_subsubfacet);
el_to_subfacet_double
= & mesh_facets.getData<std::vector<Element> >("elements_to_subfacet_double",
type_subsubfacet,
gt_subsubfacet);
facet_to_subfacet
= & mesh_facets.getElementToSubelement(type_subsubfacet,
gt_subsubfacet);
}
UInt global_ssf = subsubfacet.element;
Vector<UInt> subsubfacet_connectivity(conn_subfacet->storage()
+ global_ssf
* nb_nodes_per_sf_el,
nb_nodes_per_sf_el);
/// check if subsubfacet is to be doubled
if (findElementsAroundSubfacet<true>(mesh, mesh_facets,
starting_element, current_facet,
subsubfacet_connectivity,
element_list,
facet_list,
subfacet_list) == false &&
removeElementsInVector(*subfacet_list,
(*facet_to_subfacet)(global_ssf)) == false) {
sf_to_double->push_back(global_ssf);
sf_to_subfacet_double->push_back(*subfacet_list);
f_to_subfacet_double->push_back(facet_list);
el_to_subfacet_double->push_back(element_list);
}
}
}
else {
const UInt global_sf = subfacet.element;
Vector<UInt> subfacet_connectivity(conn_subfacet->storage()
+ global_sf
* nb_nodes_per_sf_el,
nb_nodes_per_sf_el);
/// check if subfacet is to be doubled
if (findElementsAroundSubfacet<false>(mesh, mesh_facets,
starting_element, current_facet,
subfacet_connectivity,
element_list,
facet_list) == false &&
removeElementsInVector(facet_list,
(*facet_to_subfacet)(global_sf)) == false) {
sf_to_double->push_back(global_sf);
f_to_subfacet_double->push_back(facet_list);
el_to_subfacet_double->push_back(element_list);
}
}
}
}
}
if (subsubfacet_mode)
delete subfacet_list;
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
#if defined(AKANTU_COHESIVE_ELEMENT)
void MeshUtils::updateCohesiveData(Mesh & mesh,
Mesh & mesh_facets,
Array<Element> & new_elements) {
AKANTU_DEBUG_IN();
UInt spatial_dimension = mesh.getSpatialDimension();
bool third_dimension = spatial_dimension == 3;
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType gt_facet = *gt;
Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet);
Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet);
for(; it != end; ++it) {
ElementType type_facet = *it;
Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double",
type_facet,
gt_facet);
UInt nb_facet_to_double = f_to_double.getSize();
if (nb_facet_to_double == 0) continue;
ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet);
Array<Element> * facet_to_coh_element
= mesh_facets.getSubelementToElementPointer(type_cohesive, gt_facet);
Array<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet);
Array<UInt> * conn_cohesive = mesh.getConnectivityPointer(type_cohesive,
gt_facet);
UInt nb_nodes_per_facet = Mesh::getNbNodesPerElement(type_facet);
Array< std::vector<Element> > & element_to_facet
= mesh_facets.getElementToSubelement(type_facet, gt_facet);
UInt old_nb_cohesive_elements = conn_cohesive->getSize();
UInt new_nb_cohesive_elements = conn_cohesive->getSize() + nb_facet_to_double;
UInt old_nb_facet = element_to_facet.getSize() - nb_facet_to_double;
facet_to_coh_element->resize(new_nb_cohesive_elements);
conn_cohesive->resize(new_nb_cohesive_elements);
UInt new_elements_old_size = new_elements.getSize();
new_elements.resize(new_elements_old_size + nb_facet_to_double);
Element c_element(type_cohesive, 0, gt_facet, _ek_cohesive);
Element f_element(type_facet, 0, gt_facet);
UInt facets[2];
for (UInt facet = 0; facet < nb_facet_to_double; ++facet) {
/// (in 3D cohesive elements connectivity is inverted)
facets[third_dimension] = f_to_double(facet);
facets[!third_dimension] = old_nb_facet + facet;
UInt cohesive_element = old_nb_cohesive_elements + facet;
/// store doubled facets
f_element.element = facets[0];
(*facet_to_coh_element)(cohesive_element, 0) = f_element;
f_element.element = facets[1];
(*facet_to_coh_element)(cohesive_element, 1) = f_element;
/// modify cohesive elements' connectivity
for (UInt n = 0; n < nb_nodes_per_facet; ++n) {
(*conn_cohesive)(cohesive_element, n) = conn_facet(facets[0], n);
(*conn_cohesive)(cohesive_element, n + nb_nodes_per_facet)
= conn_facet(facets[1], n);
}
/// update element_to_facet vectors
c_element.element = cohesive_element;
element_to_facet(facets[0])[1] = c_element;
element_to_facet(facets[1])[1] = c_element;
/// add cohesive element to the element event list
new_elements(new_elements_old_size + facet) = c_element;
}
}
}
AKANTU_DEBUG_OUT();
}
#endif
/* -------------------------------------------------------------------------- */
void MeshUtils::doublePointFacet(Mesh & mesh,
Mesh & mesh_facets,
Array<UInt> & doubled_nodes) {
AKANTU_DEBUG_IN();
UInt spatial_dimension = mesh.getSpatialDimension();
if (spatial_dimension != 1) return;
Array<Real> & position = mesh.getNodes();
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType gt_facet = *gt;
Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet);
Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet);
for(; it != end; ++it) {
ElementType type_facet = *it;
Array<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet);
Array< std::vector<Element> > & element_to_facet
= mesh_facets.getElementToSubelement(type_facet, gt_facet);
const Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double",
type_facet,
gt_facet);
UInt nb_facet_to_double = f_to_double.getSize();
UInt old_nb_facet = element_to_facet.getSize() - nb_facet_to_double;
UInt new_nb_facet = element_to_facet.getSize();
UInt old_nb_nodes = position.getSize();
UInt new_nb_nodes = old_nb_nodes + nb_facet_to_double;
position.resize(new_nb_nodes);
conn_facet.resize(new_nb_facet);
UInt old_nb_doubled_nodes = doubled_nodes.getSize();
doubled_nodes.resize(old_nb_doubled_nodes + nb_facet_to_double);
for (UInt facet = 0; facet < nb_facet_to_double; ++facet) {
UInt old_facet = f_to_double(facet);
UInt new_facet = old_nb_facet + facet;
ElementType type = element_to_facet(new_facet)[0].type;
UInt el = element_to_facet(new_facet)[0].element;
GhostType gt = element_to_facet(new_facet)[0].ghost_type;
UInt old_node = conn_facet(old_facet);
UInt new_node = old_nb_nodes + facet;
/// update position
position(new_node) = position(old_node);
conn_facet(new_facet) = new_node;
Array<UInt> & conn_segment = mesh.getConnectivity(type, gt);
UInt nb_nodes_per_segment = conn_segment.getNbComponent();
/// update facet connectivity
UInt i;
for (i = 0; conn_segment(el, i) != old_node
&& i <= nb_nodes_per_segment; ++i);
conn_segment(el, i) = new_node;
doubled_nodes(old_nb_doubled_nodes + facet, 0) = old_node;
doubled_nodes(old_nb_doubled_nodes + facet, 1) = new_node;
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <bool third_dim_segments>
void MeshUtils::updateQuadraticSegments(Mesh & mesh,
Mesh & mesh_facets,
ElementType type_facet,
GhostType gt_facet,
Array<UInt> & doubled_nodes) {
AKANTU_DEBUG_IN();
if (type_facet != _segment_3) return;
Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double",
type_facet,
gt_facet);
UInt nb_facet_to_double = f_to_double.getSize();
UInt old_nb_facet
= mesh_facets.getNbElement(type_facet, gt_facet) - nb_facet_to_double;
Array<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet,
gt_facet);
Array< std::vector<Element> > & element_to_facet
= mesh_facets.getElementToSubelement(type_facet, gt_facet);
/// this ones matter only for segments in 3D
Array< std::vector<Element> > * el_to_subfacet_double = NULL;
Array< std::vector<Element> > * f_to_subfacet_double = NULL;
if (third_dim_segments) {
el_to_subfacet_double
= & mesh_facets.getData<std::vector<Element> >("elements_to_subfacet_double",
type_facet,
gt_facet);
f_to_subfacet_double
= & mesh_facets.getData<std::vector<Element> >("facets_to_subfacet_double",
type_facet,
gt_facet);
}
std::vector<UInt> middle_nodes;
for (UInt facet = 0; facet < nb_facet_to_double; ++facet) {
UInt old_facet = f_to_double(facet);
UInt node = conn_facet(old_facet, 2);
if (!mesh.isPureGhostNode(node)) middle_nodes.push_back(node);
}
UInt n = doubled_nodes.getSize();
doubleNodes(mesh, middle_nodes, doubled_nodes);
for (UInt facet = 0; facet < nb_facet_to_double; ++facet) {
UInt old_facet = f_to_double(facet);
UInt old_node = conn_facet(old_facet, 2);
if (mesh.isPureGhostNode(old_node)) continue;
UInt new_node = doubled_nodes(n, 1);
UInt new_facet = old_nb_facet + facet;
conn_facet(new_facet, 2) = new_node;
if (third_dim_segments) {
updateElementalConnectivity(mesh_facets,
old_node, new_node,
element_to_facet(new_facet));
updateElementalConnectivity(mesh,
old_node, new_node,
(*el_to_subfacet_double)(facet),
&(*f_to_subfacet_double)(facet));
}
else {
updateElementalConnectivity(mesh,
old_node, new_node,
element_to_facet(new_facet));
}
++n;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::updateSubfacetToFacet(Mesh & mesh_facets,
ElementType type_subfacet,
GhostType gt_subfacet,
bool facet_mode) {
AKANTU_DEBUG_IN();
Array<UInt> & sf_to_double = mesh_facets.getData<UInt>("facet_to_double",
type_subfacet,
gt_subfacet);
UInt nb_subfacet_to_double = sf_to_double.getSize();
/// update subfacet_to_facet vector
ElementType type_facet = _not_defined;
GhostType gt_facet = _casper;
Array<Element> * subfacet_to_facet = NULL;
UInt nb_subfacet_per_facet = 0;
UInt old_nb_subfacet
= mesh_facets.getNbElement(type_subfacet, gt_subfacet) - nb_subfacet_to_double;
Array<std::vector<Element> > * facet_list = NULL;
if (facet_mode)
facet_list = & mesh_facets.getData<std::vector<Element> >("facets_to_subfacet_double",
type_subfacet,
gt_subfacet);
else
facet_list = & mesh_facets.getData<std::vector<Element> >("subfacets_to_subsubfacet_double",
type_subfacet,
gt_subfacet);
Element old_subfacet_el(type_subfacet, 0, gt_subfacet);
Element new_subfacet_el(type_subfacet, 0, gt_subfacet);
for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) {
old_subfacet_el.element = sf_to_double(sf);
new_subfacet_el.element = old_nb_subfacet + sf;
for (UInt f = 0; f < (*facet_list)(sf).size(); ++f) {
Element & facet = (*facet_list)(sf)[f];
if (facet.type != type_facet || facet.ghost_type != gt_facet) {
type_facet = facet.type;
gt_facet = facet.ghost_type;
subfacet_to_facet = & mesh_facets.getSubelementToElement(type_facet,
gt_facet);
nb_subfacet_per_facet = subfacet_to_facet->getNbComponent();
}
Element * sf_update
= std::find(subfacet_to_facet->storage()
+ facet.element * nb_subfacet_per_facet,
subfacet_to_facet->storage()
+ facet.element * nb_subfacet_per_facet + nb_subfacet_per_facet,
old_subfacet_el);
AKANTU_DEBUG_ASSERT(subfacet_to_facet->storage()
+ facet.element * nb_subfacet_per_facet !=
subfacet_to_facet->storage()
+ facet.element * nb_subfacet_per_facet + nb_subfacet_per_facet,
"Subfacet not found");
*sf_update = new_subfacet_el;
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::updateFacetToSubfacet(Mesh & mesh_facets,
ElementType type_subfacet,
GhostType gt_subfacet,
bool facet_mode) {
AKANTU_DEBUG_IN();
Array<UInt> & sf_to_double = mesh_facets.getData<UInt>("facet_to_double",
type_subfacet,
gt_subfacet);
UInt nb_subfacet_to_double = sf_to_double.getSize();
Array< std::vector<Element> > & facet_to_subfacet
= mesh_facets.getElementToSubelement(type_subfacet, gt_subfacet);
Array< std::vector<Element> > * facet_to_subfacet_double = NULL;
if (facet_mode) {
facet_to_subfacet_double
= & mesh_facets.getData<std::vector<Element> >("facets_to_subfacet_double",
type_subfacet,
gt_subfacet);
}
else {
facet_to_subfacet_double
= & mesh_facets.getData<std::vector<Element> >("subfacets_to_subsubfacet_double",
type_subfacet,
gt_subfacet);
}
UInt old_nb_subfacet = facet_to_subfacet.getSize();
facet_to_subfacet.resize(old_nb_subfacet + nb_subfacet_to_double);
for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf)
facet_to_subfacet(old_nb_subfacet + sf) = (*facet_to_subfacet_double)(sf);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <UInt spatial_dimension>
void MeshUtils::doubleSubfacet(Mesh & mesh,
Mesh & mesh_facets,
Array<UInt> & doubled_nodes) {
AKANTU_DEBUG_IN();
if (spatial_dimension == 1) return;
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType gt_subfacet = *gt;
Mesh::type_iterator it = mesh_facets.firstType(0, gt_subfacet);
Mesh::type_iterator end = mesh_facets.lastType(0, gt_subfacet);
for(; it != end; ++it) {
ElementType type_subfacet = *it;
Array<UInt> & sf_to_double = mesh_facets.getData<UInt>("facet_to_double",
type_subfacet,
gt_subfacet);
UInt nb_subfacet_to_double = sf_to_double.getSize();
if (nb_subfacet_to_double == 0) continue;
AKANTU_DEBUG_ASSERT(type_subfacet == _point_1,
"Only _point_1 subfacet doubling is supported at the moment");
Array<UInt> & conn_subfacet = mesh_facets.getConnectivity(type_subfacet,
gt_subfacet);
UInt old_nb_subfacet = conn_subfacet.getSize();
UInt new_nb_subfacet = old_nb_subfacet + nb_subfacet_to_double;
conn_subfacet.resize(new_nb_subfacet);
std::vector<UInt> nodes_to_double;
UInt old_nb_doubled_nodes = doubled_nodes.getSize();
/// double nodes
for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) {
UInt old_subfacet = sf_to_double(sf);
nodes_to_double.push_back(conn_subfacet(old_subfacet));
}
doubleNodes(mesh, nodes_to_double, doubled_nodes);
/// add new nodes in connectivity
for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) {
UInt new_subfacet = old_nb_subfacet + sf;
UInt new_node = doubled_nodes(old_nb_doubled_nodes + sf, 1);
conn_subfacet(new_subfacet) = new_node;
}
/// update facet and element connectivity
Array<std::vector<Element> > & f_to_subfacet_double =
mesh_facets.getData<std::vector<Element> >("facets_to_subfacet_double",
type_subfacet,
gt_subfacet);
Array<std::vector<Element> > & el_to_subfacet_double =
mesh_facets.getData<std::vector<Element> >("elements_to_subfacet_double",
type_subfacet,
gt_subfacet);
Array<std::vector<Element> > * sf_to_subfacet_double = NULL;
if (spatial_dimension == 3)
sf_to_subfacet_double
= & mesh_facets.getData<std::vector<Element> >("subfacets_to_subsubfacet_double",
type_subfacet,
gt_subfacet);
for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) {
UInt old_node = doubled_nodes(old_nb_doubled_nodes + sf, 0);
UInt new_node = doubled_nodes(old_nb_doubled_nodes + sf, 1);
updateElementalConnectivity(mesh,
old_node, new_node,
el_to_subfacet_double(sf),
&f_to_subfacet_double(sf));
updateElementalConnectivity(mesh_facets,
old_node, new_node,
f_to_subfacet_double(sf));
if (spatial_dimension == 3)
updateElementalConnectivity(mesh_facets,
old_node, new_node,
(*sf_to_subfacet_double)(sf));
}
if (spatial_dimension == 2) {
updateSubfacetToFacet(mesh_facets, type_subfacet, gt_subfacet, true);
updateFacetToSubfacet(mesh_facets, type_subfacet, gt_subfacet, true);
}
else if (spatial_dimension == 3) {
updateSubfacetToFacet(mesh_facets, type_subfacet, gt_subfacet, false);
updateFacetToSubfacet(mesh_facets, type_subfacet, gt_subfacet, false);
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::flipFacets(Mesh & mesh_facets,
const ElementTypeMapArray<UInt> & global_connectivity,
GhostType gt_facet) {
AKANTU_DEBUG_IN();
UInt spatial_dimension = mesh_facets.getSpatialDimension();
/// get global connectivity for local mesh
ElementTypeMapArray<UInt> global_connectivity_tmp;
mesh_facets.initElementTypeMapArray(global_connectivity_tmp, 1,
spatial_dimension - 1, gt_facet,
true, _ek_regular, true);
mesh_facets.getGlobalConnectivity(global_connectivity_tmp,
spatial_dimension - 1, gt_facet);
Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet);
Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet);
/// loop on every facet
for(; it != end; ++it) {
ElementType type_facet = *it;
Array<UInt> & connectivity = mesh_facets.getConnectivity(type_facet, gt_facet);
const Array<UInt> & g_connectivity = global_connectivity(type_facet, gt_facet);
Array<std::vector<Element> > & el_to_f =
mesh_facets.getElementToSubelement(type_facet, gt_facet);
Array<Element> & subfacet_to_facet =
mesh_facets.getSubelementToElement(type_facet, gt_facet);
UInt nb_subfacet_per_facet = subfacet_to_facet.getNbComponent();
UInt nb_nodes_per_facet = connectivity.getNbComponent();
UInt nb_facet = connectivity.getSize();
UInt nb_nodes_per_P1_facet
= Mesh::getNbNodesPerElement(Mesh::getP1ElementType(type_facet));
Array<UInt> & global_conn_tmp = global_connectivity_tmp(type_facet, gt_facet);
Array<UInt>::iterator<Vector<UInt> > conn_it =
connectivity.begin(nb_nodes_per_facet);
Array<UInt>::iterator<Vector<UInt> > gconn_tmp_it =
global_conn_tmp.begin(nb_nodes_per_facet);
Array<UInt>::const_iterator<Vector<UInt> > conn_glob_it =
g_connectivity.begin(nb_nodes_per_facet);
Array<Element>::iterator<Vector<Element> > subf_to_f =
subfacet_to_facet.begin(nb_subfacet_per_facet);
UInt * conn_tmp_pointer = new UInt[nb_nodes_per_facet];
Vector<UInt> conn_tmp(conn_tmp_pointer, nb_nodes_per_facet);
Element el_tmp;
Element * subf_tmp_pointer = new Element[nb_subfacet_per_facet];
Vector<Element> subf_tmp(subf_tmp_pointer, nb_subfacet_per_facet);
for (UInt f = 0; f < nb_facet; ++f, ++conn_it, ++gconn_tmp_it,
++subf_to_f, ++conn_glob_it) {
Vector<UInt> & gconn_tmp = *gconn_tmp_it;
const Vector<UInt> & conn_glob = *conn_glob_it;
Vector<UInt> & conn_local = *conn_it;
/// skip facet if connectivities are the same
if (gconn_tmp == conn_glob) continue;
/// re-arrange connectivity
conn_tmp = conn_local;
UInt * begin = conn_glob.storage();
UInt * end = conn_glob.storage() + nb_nodes_per_facet;
for (UInt n = 0; n < nb_nodes_per_facet; ++n) {
UInt * new_node = std::find(begin, end, gconn_tmp(n));
AKANTU_DEBUG_ASSERT(new_node != end, "Node not found");
UInt new_position = new_node - begin;
conn_local(new_position) = conn_tmp(n);
}
/// if 3D, check if facets are just rotated
if (spatial_dimension == 3) {
/// find first node
UInt * new_node = std::find(begin, end, gconn_tmp(0));
AKANTU_DEBUG_ASSERT(new_node != end, "Node not found");
UInt new_position = new_node - begin;
UInt n = 1;
/// count how many nodes in the received connectivity follow
/// the same order of those in the local connectivity
for (; n < nb_nodes_per_P1_facet &&
gconn_tmp(n) == conn_glob((new_position + n) % nb_nodes_per_P1_facet);
++n);
/// skip the facet inversion if facet is just rotated
if (n == nb_nodes_per_P1_facet) continue;
}
/// update data to invert facet
el_tmp = el_to_f(f)[0];
el_to_f(f)[0] = el_to_f(f)[1];
el_to_f(f)[1] = el_tmp;
subf_tmp = (*subf_to_f);
(*subf_to_f)(0) = subf_tmp(1);
(*subf_to_f)(1) = subf_tmp(0);
}
delete [] subf_tmp_pointer;
delete [] conn_tmp_pointer;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::fillElementToSubElementsData(Mesh & mesh) {
AKANTU_DEBUG_IN();
if(mesh.getNbElement(mesh.getSpatialDimension() - 1) == 0) {
AKANTU_DEBUG_INFO("There are not facets, add them in the mesh file or call the buildFacet method.");
return;
}
UInt spatial_dimension = mesh.getSpatialDimension();
ElementTypeMapArray<Real> barycenters("barycenter_tmp", mesh.getID());
mesh.initElementTypeMapArray(barycenters,
spatial_dimension,
_all_dimensions);
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end();
++gt) {
Mesh::type_iterator it = mesh.firstType(_all_dimensions, *gt);
Mesh::type_iterator end = mesh.lastType(_all_dimensions, *gt);
for(; it != end; ++it) {
UInt nb_element = mesh.getNbElement(*it, *gt);
Array<Real> & barycenters_arr = barycenters(*it, *gt);
barycenters_arr.resize(nb_element);
Array<Real>::vector_iterator bary = barycenters_arr.begin(spatial_dimension);
Array<Real>::vector_iterator bary_end = barycenters_arr.end(spatial_dimension);
for (UInt el = 0; bary != bary_end; ++bary, ++el) {
mesh.getBarycenter(el, *it, bary->storage(), *gt);
}
}
}
for(Int sp(spatial_dimension); sp >= 1; --sp) {
if(mesh.getNbElement(sp) == 0) continue;
for (ghost_type_t::iterator git = ghost_type_t::begin(); git != ghost_type_t::end(); ++git) {
Mesh::type_iterator tit = mesh.firstType(sp, *git);
Mesh::type_iterator tend = mesh.lastType(sp, *git);
for (;tit != tend; ++tit) {
mesh.getSubelementToElementPointer(*tit, *git)->resize(mesh.getNbElement(*tit, *git));
mesh.getSubelementToElement(*tit, *git).clear();
}
tit = mesh.firstType(sp - 1, *git);
tend = mesh.lastType(sp - 1, *git);
for (;tit != tend; ++tit) {
mesh.getElementToSubelementPointer(*tit, *git)->resize(mesh.getNbElement(*tit, *git));
mesh.getElementToSubelement(*tit, *git).clear();
}
}
CSR<Element> nodes_to_elements;
buildNode2Elements(mesh, nodes_to_elements, sp);
Element facet_element;
for (ghost_type_t::iterator git = ghost_type_t::begin(); git != ghost_type_t::end(); ++git) {
Mesh::type_iterator tit = mesh.firstType(sp - 1, *git);
Mesh::type_iterator tend = mesh.lastType(sp - 1, *git);
facet_element.ghost_type = *git;
for (;tit != tend; ++tit) {
facet_element.type = *tit;
Array< std::vector<Element> > & element_to_subelement = mesh.getElementToSubelement(*tit, *git);
const Array<UInt> & connectivity = mesh.getConnectivity(*tit, *git);
Array<UInt>::const_iterator< Vector<UInt> > fit = connectivity.begin(mesh.getNbNodesPerElement(*tit));
Array<UInt>::const_iterator< Vector<UInt> > fend = connectivity.end(mesh.getNbNodesPerElement(*tit));
UInt fid = 0;
for (;fit != fend; ++fit, ++fid) {
const Vector<UInt> & facet = *fit;
facet_element.element = fid;
std::map<Element, UInt> element_seen_counter;
UInt nb_nodes_per_facet = mesh.getNbNodesPerElement(Mesh::getP1ElementType(*tit));
for (UInt n(0); n < nb_nodes_per_facet; ++n) {
CSR<Element>::iterator eit = nodes_to_elements.begin(facet(n));
CSR<Element>::iterator eend = nodes_to_elements.end(facet(n));
for(;eit != eend; ++eit) {
Element & elem = *eit;
std::map<Element, UInt>::iterator cit = element_seen_counter.find(elem);
if(cit != element_seen_counter.end()) {
cit->second++;
} else {
element_seen_counter[elem] = 1;
}
}
}
std::vector<Element> connected_elements;
std::map<Element, UInt>::iterator cit = element_seen_counter.begin();
std::map<Element, UInt>::iterator cend = element_seen_counter.end();
for(;cit != cend; ++cit) {
if(cit->second == nb_nodes_per_facet) connected_elements.push_back(cit->first);
}
std::vector<Element>::iterator ceit = connected_elements.begin();
std::vector<Element>::iterator ceend = connected_elements.end();
for(;ceit != ceend; ++ceit)
element_to_subelement(fid).push_back(*ceit);
for (UInt ce = 0; ce < connected_elements.size(); ++ce) {
Element & elem = connected_elements[ce];
Array<Element> & subelement_to_element =
*(mesh.getSubelementToElementPointer(elem.type,
elem.ghost_type));
UInt f(0);
for(; f < mesh.getNbFacetsPerElement(elem.type) &&
subelement_to_element(elem.element, f) != ElementNull; ++f);
AKANTU_DEBUG_ASSERT(f < mesh.getNbFacetsPerElement(elem.type), "The element " << elem << " seems to have too many facets!! (" << f << " < " << mesh.getNbFacetsPerElement(elem.type) << ")");
subelement_to_element(elem.element, f) = facet_element;
}
}
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <bool third_dim_points>
bool MeshUtils::findElementsAroundSubfacet(const Mesh & mesh,
const Mesh & mesh_facets,
const Element & starting_element,
const Element & end_facet,
const Vector<UInt> & subfacet_connectivity,
std::vector<Element> & elem_list,
std::vector<Element> & facet_list,
std::vector<Element> * subfacet_list) {
AKANTU_DEBUG_IN();
/// preallocated stuff before starting
bool facet_matched = false;
elem_list.clear();
facet_list.clear();
if (third_dim_points)
subfacet_list->clear();
elem_list.push_back(starting_element);
const Array<UInt> * facet_connectivity = NULL;
const Array<UInt> * sf_connectivity = NULL;
const Array<Element> * facet_to_element = NULL;
const Array<Element> * subfacet_to_facet = NULL;
ElementType current_type = _not_defined;
GhostType current_ghost_type = _casper;
ElementType current_facet_type = _not_defined;
GhostType current_facet_ghost_type = _casper;
ElementType current_subfacet_type = _not_defined;
GhostType current_subfacet_ghost_type = _casper;
const Array< std::vector<Element> > * element_to_facet = NULL;
const Element * opposing_el = NULL;
std::queue<Element> elements_to_check;
elements_to_check.push(starting_element);
/// keep going until there are elements to check
while (!elements_to_check.empty()) {
/// check current element
Element & current_el = elements_to_check.front();
if (current_el.type != current_type ||
current_el.ghost_type != current_ghost_type) {
current_type = current_el.type;
current_ghost_type = current_el.ghost_type;
facet_to_element = & mesh_facets.getSubelementToElement(current_type,
current_ghost_type);
}
/// loop over each facet of the element
for (UInt f = 0; f < facet_to_element->getNbComponent(); ++f) {
const Element & current_facet = (*facet_to_element)(current_el.element, f);
if (current_facet == ElementNull) continue;
if (current_facet_type != current_facet.type ||
current_facet_ghost_type != current_facet.ghost_type) {
current_facet_type = current_facet.type;
current_facet_ghost_type = current_facet.ghost_type;
element_to_facet =
& mesh_facets.getElementToSubelement(current_facet_type,
current_facet_ghost_type);
facet_connectivity = & mesh_facets.getConnectivity(current_facet_type,
current_facet_ghost_type);
if (third_dim_points)
subfacet_to_facet =
& mesh_facets.getSubelementToElement(current_facet_type,
current_facet_ghost_type);
}
/// check if end facet is reached
if (current_facet == end_facet)
facet_matched = true;
/// add this facet if not already passed
if (std::find(facet_list.begin(),
facet_list.end(),
current_facet) == facet_list.end() &&
hasElement(*facet_connectivity, current_facet, subfacet_connectivity)) {
facet_list.push_back(current_facet);
if (third_dim_points) {
/// check subfacets
for (UInt sf = 0; sf < subfacet_to_facet->getNbComponent(); ++sf) {
const Element & current_subfacet
= (*subfacet_to_facet)(current_facet.element, sf);
if (current_subfacet == ElementNull) continue;
if (current_subfacet_type != current_subfacet.type ||
current_subfacet_ghost_type != current_subfacet.ghost_type) {
current_subfacet_type = current_subfacet.type;
current_subfacet_ghost_type = current_subfacet.ghost_type;
sf_connectivity
= & mesh_facets.getConnectivity(current_subfacet_type,
current_subfacet_ghost_type);
}
if (std::find(subfacet_list->begin(),
subfacet_list->end(),
current_subfacet) == subfacet_list->end() &&
hasElement(*sf_connectivity, current_subfacet, subfacet_connectivity))
subfacet_list->push_back(current_subfacet);
}
}
}
else
continue;
/// consider opposing element
if ( (*element_to_facet)(current_facet.element)[0] == current_el)
opposing_el = & (*element_to_facet)(current_facet.element)[1];
else
opposing_el = & (*element_to_facet)(current_facet.element)[0];
/// skip null elements since they are on a boundary
if (*opposing_el == ElementNull) continue;
/// skip this element if already added
if ( std::find(elem_list.begin(),
elem_list.end(),
*opposing_el) != elem_list.end() ) continue;
/// only regular elements have to be checked
if (opposing_el->kind == _ek_regular)
elements_to_check.push(*opposing_el);
elem_list.push_back(*opposing_el);
#ifndef AKANTU_NDEBUG
const Array<UInt> & conn_elem = mesh.getConnectivity(opposing_el->type,
opposing_el->ghost_type);
AKANTU_DEBUG_ASSERT(hasElement(conn_elem, *opposing_el, subfacet_connectivity),
"Subfacet doesn't belong to this element");
#endif
}
/// erased checked element from the list
elements_to_check.pop();
}
AKANTU_DEBUG_OUT();
return facet_matched;
}
/* -------------------------------------------------------------------------- */
void MeshUtils::buildSegmentToNodeType(const Mesh & mesh,
Mesh & mesh_facets,
DistributedSynchronizer * synchronizer) {
buildAllFacets(mesh, mesh_facets, 1, synchronizer);
UInt spatial_dimension = mesh.getSpatialDimension();
const ElementTypeMapArray<UInt> & element_to_rank = synchronizer->getPrankToElement();
Int local_rank = StaticCommunicator::getStaticCommunicator().whoAmI();
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end();
++gt) {
GhostType ghost_type = *gt;
Mesh::type_iterator it = mesh_facets.firstType(1, ghost_type);
Mesh::type_iterator end = mesh_facets.lastType(1, ghost_type);
for(; it != end; ++it) {
ElementType type = *it;
UInt nb_segments = mesh_facets.getNbElement(type, ghost_type);
// allocate the data
Array<Int> & segment_to_nodetype =
*(mesh_facets.getDataPointer<Int>("segment_to_nodetype", type, ghost_type));
std::set<Element> connected_elements;
const Array< std::vector<Element> > & segment_to_2Delement
= mesh_facets.getElementToSubelement(type, ghost_type);
// loop over segments
for (UInt s = 0; s < nb_segments; ++s) {
// determine the elements connected to the segment
connected_elements.clear();
const std::vector<Element> & twoD_elements = segment_to_2Delement(s);
if (spatial_dimension == 2) {
// if 2D just take the elements connected to the segments
connected_elements.insert(twoD_elements.begin(), twoD_elements.end());
} else if (spatial_dimension == 3) {
// if 3D a second loop is needed to get to the 3D elements
std::vector<Element>::const_iterator facet = twoD_elements.begin();
for (; facet != twoD_elements.end(); ++facet) {
const std::vector<Element> & threeD_elements
= mesh_facets.getElementToSubelement(facet->type, facet->ghost_type)(facet->element);
connected_elements.insert(threeD_elements.begin(), threeD_elements.end());
}
}
// get the minimum processor rank associated to the connected
// elements and verify if ghost and not ghost elements are
// found
Int minimum_rank = std::numeric_limits<Int>::max();
// two booleans saying if not ghost and ghost elements are found in the loop
bool ghost_found[2];
ghost_found[0] = false; ghost_found[1] = false;
std::set<Element>::iterator connected_elements_it = connected_elements.begin();
for (; connected_elements_it != connected_elements.end(); ++connected_elements_it) {
if (*connected_elements_it == ElementNull) continue;
ghost_found[connected_elements_it->ghost_type] = true;
const Array<UInt> & el_to_rank_array = element_to_rank(connected_elements_it->type,
connected_elements_it->ghost_type);
minimum_rank = std::min(minimum_rank, Int(el_to_rank_array(connected_elements_it->element)));
}
// if no ghost elements are found the segment is local
if (!ghost_found[1]) segment_to_nodetype(s) = -1;
// if no not ghost elements are found the segment is pure ghost
else if (!ghost_found[0]) segment_to_nodetype(s) = -3;
// if the minimum rank is equal to the local rank, the segment is master
else if (local_rank == minimum_rank) segment_to_nodetype(s) = -2;
// if the minimum rank is less than the local rank, the segment is slave
else if (local_rank > minimum_rank) segment_to_nodetype(s) = minimum_rank;
else AKANTU_DEBUG_ERROR("The local rank cannot be smaller than the minimum rank if both ghost and not ghost elements are found");
}
}
}
}
/* -------------------------------------------------------------------------- */
UInt MeshUtils::updateLocalMasterGlobalConnectivity(Mesh & mesh, UInt local_nb_new_nodes) {
StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
Int rank = comm.whoAmI();
Int nb_proc = comm.getNbProc();
if (nb_proc == 1) return local_nb_new_nodes;
/// resize global ids array
Array<UInt> & nodes_global_ids = mesh.getGlobalNodesIds();
UInt old_nb_nodes = mesh.getNbNodes() - local_nb_new_nodes;
nodes_global_ids.resize(mesh.getNbNodes());
/// compute the number of global nodes based on the number of old nodes
Vector<UInt> old_local_master_nodes(nb_proc);
for (UInt n = 0; n < old_nb_nodes; ++n)
if (mesh.isLocalOrMasterNode(n)) ++old_local_master_nodes(rank);
comm.allGather(old_local_master_nodes.storage(), 1);
UInt old_global_nodes = std::accumulate(old_local_master_nodes.storage(),
old_local_master_nodes.storage() + nb_proc,
0);
/// compute amount of local or master doubled nodes
Vector<UInt> local_master_nodes(nb_proc);
for (UInt n = old_nb_nodes; n < mesh.getNbNodes(); ++n)
if (mesh.isLocalOrMasterNode(n)) ++local_master_nodes(rank);
comm.allGather(local_master_nodes.storage(), 1);
/// update global number of nodes
UInt total_nb_new_nodes = std::accumulate(local_master_nodes.storage(),
local_master_nodes.storage() + nb_proc,
0);
if (total_nb_new_nodes == 0) return 0;
/// set global ids of local and master nodes
UInt starting_index = std::accumulate(local_master_nodes.storage(),
local_master_nodes.storage() + rank,
old_global_nodes);
for (UInt n = old_nb_nodes; n < mesh.getNbNodes(); ++n) {
if (mesh.isLocalOrMasterNode(n)) {
nodes_global_ids(n) = starting_index;
++starting_index;
}
}
mesh.nb_global_nodes = old_global_nodes + total_nb_new_nodes;
return total_nb_new_nodes;
}
/* -------------------------------------------------------------------------- */
__END_AKANTU__
// LocalWords: ElementType
Event Timeline
Log In to Comment