#include <boundary_info.h>
~BoundaryInfo ()
void clear ()
void sync (BoundaryMesh &boundary_mesh, MeshData *boundary_mesh_data=NULL, MeshData *this_mesh_data=NULL)
void sync (const std::set< short int > &requested_boundary_ids, BoundaryMesh &boundary_mesh)
void add_node (const Node *node, const short int id)
void add_node (const unsigned int node, const short int id)
void add_side (const unsigned int elem, const unsigned short int side, const short int id)
void add_side (const Elem *elem, const unsigned short int side, const short int id)
void remove (const Node *node)
void remove (const Elem *elem)
void remove_side (const Elem *elem, const unsigned short int side)
void remove_side (const Elem *elem, const unsigned short int side, const short int id)
unsigned int n_boundary_ids () const
std::vector< short int > boundary_ids (const Node *node) const
short int boundary_id (const Elem *const elem, const unsigned short int side) const
unsigned int side_with_boundary_id (const Elem *const elem, const unsigned short int boundary_id) const
void build_node_boundary_ids (std::vector< short int > &b_ids)
void build_side_boundary_ids (std::vector< short int > &b_ids)
unsigned int n_boundary_conds () const
void build_node_list (std::vector< unsigned int > &nl, std::vector< short int > &il) const
void build_node_list_from_side_list ()
void build_side_list (std::vector< unsigned int > &el, std::vector< unsigned short int > &sl, std::vector< short int > &il) const
const std::set< short int > & get_boundary_ids () const
void print_info () const
static const short int invalid_id = -1234
BoundaryInfo (const MeshBase &m)
const MeshBase & _mesh
std::multimap< const Node *, short int > _boundary_node_id
std::multimap< const Elem *, std::pair< unsigned short int, short int > > _boundary_side_id
std::set< short int > _boundary_ids
The BoundaryInfo class contains information relevant to boundary conditions: it does not hold actual boundary condition data (check MeshData for that), but can mark element faces and nodes with ids useful for identifying the type of boundary condtion. It can also build a mesh that just includes boundary elements/faces.
TODO[JWP]: Generalize this to work with MeshBase again.
Definition at line 55 of file boundary_info.h.
Definition at line 43 of file boundary_info.C.
:
_mesh (m)
{
}
Definition at line 50 of file boundary_info.C.
References clear().
{
this->clear();
}
Definition at line 323 of file boundary_info.C.
References _boundary_ids, _boundary_node_id, and invalid_id.
Referenced by add_node(), and build_node_list_from_side_list().
{
if (id == invalid_id)
{
std::cerr << 'ERROR: You may not set a boundary ID of '
<< invalid_id << std::endl
<< ' That is reserved for internal use.
<< std::endl;
libmesh_error();
}
// A convenient typedef
typedef std::multimap<const Node*, short int>::const_iterator Iter;
// Don't add the same ID twice
std::pair<Iter, Iter> pos = _boundary_node_id.equal_range(node);
for (;pos.first != pos.second; ++pos.first)
if (pos.first->second == id)
return;
std::pair<const Node*, short int> kv (node, id);
_boundary_node_id.insert(kv);
_boundary_ids.insert(id);
}
Definition at line 315 of file boundary_info.C.
References _mesh, add_node(), and MeshBase::node_ptr().
{
this->add_node (_mesh.node_ptr(node), id);
}
Definition at line 354 of file boundary_info.C.
References _mesh, and MeshBase::elem().
Referenced by XdrIO::read_serialized_bcs().
{
this->add_side (_mesh.elem(e), side, id);
}
Definition at line 363 of file boundary_info.C.
References _boundary_ids, _boundary_side_id, invalid_id, and Elem::level().
{
libmesh_assert (elem != NULL);
// Only add BCs for level-0 elements.
libmesh_assert (elem->level() == 0);
if (id == invalid_id)
{
std::cerr << 'ERROR: You may not set a boundary ID of '
<< invalid_id << std::endl
<< ' That is reserved for internal use.
<< std::endl;
libmesh_error();
}
// A convenient typedef
typedef std::multimap<const Elem*, std::pair<unsigned short int, short int> >::const_iterator Iter;
// Don't add the same ID twice
std::pair<Iter, Iter> pos = _boundary_side_id.equal_range(elem);
for (;pos.first != pos.second; ++pos.first)
if (pos.first->second.first == side &&
pos.first->second.second == id)
return;
std::pair<unsigned short int, short int> p(side,id);
std::pair<const Elem*, std::pair<unsigned short int, short int> >
kv (elem, p);
_boundary_side_id.insert(kv);
_boundary_ids.insert(id);
}
Definition at line 421 of file boundary_info.C.
References _boundary_side_id, invalid_id, Elem::level(), and Elem::top_parent().
Referenced by XdrIO::write_serialized_bcs().
{
libmesh_assert (elem != NULL);
// Only level-0 elements store BCs. If this is not a level-0
// element get its level-0 parent and infer the BCs.
const Elem* searched_elem = elem;
if (elem->level() != 0)
searched_elem = elem->top_parent ();
std::pair<std::multimap<const Elem*,
std::pair<unsigned short int, short int> >::const_iterator,
std::multimap<const Elem*,
std::pair<unsigned short int, short int> >::const_iterator >
e = _boundary_side_id.equal_range(searched_elem);
// elem not in the data structure
if (e.first == e.second)
return invalid_id;
// elem is there, maybe multiple occurances
while (e.first != e.second)
{
// if this is true we found the requested side
// of the element and want to return the id
if (e.first->second.first == side)
return e.first->second.second;
++e.first;
}
// if we get here, we found elem in the data structure but not
// the requested side, so return the default value
return invalid_id;
}
Definition at line 403 of file boundary_info.C.
References _boundary_node_id.
{
std::vector<short int> ids;
// A convenient typedef
typedef std::multimap<const Node*, short int>::const_iterator Iter;
// Don't add the same ID twice
std::pair<Iter, Iter> pos = _boundary_node_id.equal_range(node);
for (;pos.first != pos.second; ++pos.first)
ids.push_back(pos.first->second);
return ids;
}
Definition at line 558 of file boundary_info.C.
References _boundary_node_id.
{
b_ids.clear();
std::multimap<const Node*, short int>::const_iterator pos
= _boundary_node_id.begin();
for (; pos != _boundary_node_id.end(); ++pos)
{
short int id = pos->second;
if(std::find(b_ids.begin(),b_ids.end(),id) == b_ids.end())
b_ids.push_back(id);
}
}
Definition at line 617 of file boundary_info.C.
References _boundary_node_id.
{
// Reserve the size, then use push_back
nl.reserve (_boundary_node_id.size());
il.reserve (_boundary_node_id.size());
std::multimap<const Node*, short int>::const_iterator pos
= _boundary_node_id.begin();
for (; pos != _boundary_node_id.end(); ++pos)
{
nl.push_back (pos->first->id());
il.push_back (pos->second);
}
}
Definition at line 636 of file boundary_info.C.
References _boundary_side_id, Elem::active_family_tree_by_side(), add_node(), and Elem::build_side().
{
std::multimap<const Elem*,
std::pair<unsigned short int,
short int> >::const_iterator pos;
//Loop over the side list
for (pos=_boundary_side_id.begin(); pos != _boundary_side_id.end(); ++pos)
{
//Need to loop over the sides of any possible children
std::vector< const Elem * > family;
#ifdef LIBMESH_ENABLE_AMR
pos->first->active_family_tree_by_side (family, pos->second.first);
#else
family.push_back(pos->first);
#endif
for(unsigned int elem_it=0; elem_it < family.size(); elem_it++)
{
const Elem * cur_elem = family[elem_it];
AutoPtr<Elem> side = cur_elem->build_side(pos->second.first);
//Add each node node on the side with the side's boundary id
for(unsigned int i=0; i<side->n_nodes(); i++)
{
Node * node = side->get_node(i);
this->add_node(node, pos->second.second);
}
}
}
}
Definition at line 574 of file boundary_info.C.
References _boundary_side_id.
{
b_ids.clear();
std::multimap<const Elem*, std::pair<unsigned short int, short int> >::const_iterator pos
= _boundary_side_id.begin();
for (; pos != _boundary_side_id.end(); ++pos)
{
short int id = pos->second.second;
if(std::find(b_ids.begin(),b_ids.end(),id) == b_ids.end())
b_ids.push_back(id);
}
}
Definition at line 670 of file boundary_info.C.
References _boundary_side_id.
{
// Reserve the size, then use push_back
el.reserve (_boundary_side_id.size());
sl.reserve (_boundary_side_id.size());
il.reserve (_boundary_side_id.size());
std::multimap<const Elem*,
std::pair<unsigned short int,
short int> >::const_iterator pos;
for (pos=_boundary_side_id.begin(); pos != _boundary_side_id.end();
++pos)
{
el.push_back (pos->first->id());
sl.push_back (pos->second.first);
il.push_back (pos->second.second);
}
}
Definition at line 57 of file boundary_info.C.
References _boundary_ids, _boundary_node_id, and _boundary_side_id.
Referenced by ~BoundaryInfo().
{
_boundary_node_id.clear();
_boundary_side_id.clear();
_boundary_ids.clear();
}
Definition at line 239 of file boundary_info.h.
References _boundary_ids.
{ return _boundary_ids; }
Definition at line 590 of file boundary_info.C.
References _boundary_side_id, _mesh, MeshBase::is_serial(), and libMesh::processor_id().
{
// in serial we know the number of bcs from the
// size of the container
if (_mesh.is_serial())
return _boundary_side_id.size();
// in parallel we need to sum the number of local bcs
parallel_only();
unsigned int nbcs=0;
std::multimap<const Elem*,
std::pair<unsigned short int,
short int> >::const_iterator pos;
for (pos=_boundary_side_id.begin(); pos != _boundary_side_id.end(); ++pos)
if (pos->first->processor_id() == libMesh::processor_id())
nbcs++;
Parallel::sum (nbcs);
return nbcs;
}
Definition at line 174 of file boundary_info.h.
References _boundary_ids.
{ return _boundary_ids.size(); }
Definition at line 694 of file boundary_info.C.
References _boundary_node_id, and _boundary_side_id.
{
// Print out the nodal BCs
if (!_boundary_node_id.empty())
{
std::cout << 'Nodal Boundary conditions:' << std::endl
<< '--------------------------' << std::endl
<< ' (Node No., ID) ' << std::endl;
// std::for_each(_boundary_node_id.begin(),
// _boundary_node_id.end(),
// PrintNodeInfo());
std::multimap<const Node*, short int>::const_iterator it = _boundary_node_id.begin();
const std::multimap<const Node*, short int>::const_iterator end = _boundary_node_id.end();
for (; it != end; ++it)
std::cout << ' (' << (*it).first->id()
<< ', ' << (*it).second
<< ')' << std::endl;
}
// Print out the element BCs
if (!_boundary_side_id.empty())
{
std::cout << std::endl
<< 'Side Boundary conditions:' << std::endl
<< '-------------------------' << std::endl
<< ' (Elem No., Side No., ID) ' << std::endl;
// std::for_each(_boundary_side_id.begin(),
// _boundary_side_id.end(),
// PrintSideInfo());
std::multimap<const Elem*,
std::pair<unsigned short int, short int> >::const_iterator it = _boundary_side_id.begin();
const std::multimap<const Elem*,
std::pair<unsigned short int, short int> >::const_iterator end = _boundary_side_id.end();
for (; it != end; ++it)
std::cout << ' (' << (*it).first->id()
<< ', ' << (*it).second.first
<< ', ' << (*it).second.second
<< ')' << std::endl;
}
}
Definition at line 370 of file boundary_info.h.
References _boundary_side_id.
{
libmesh_assert (elem != NULL);
// Erase everything associated with elem
_boundary_side_id.erase (elem);
}
Definition at line 359 of file boundary_info.h.
References _boundary_node_id.
{
libmesh_assert (node != NULL);
// Erase everything associated with node
_boundary_node_id.erase (node);
}
Definition at line 491 of file boundary_info.C.
References _boundary_side_id, and Elem::level().
{
libmesh_assert (elem != NULL);
// The user shouldn't be trying to remove only one child's boundary
// id
libmesh_assert (elem->level() == 0);
std::pair<std::multimap<const Elem*,
std::pair<unsigned short int, short int> >::iterator,
std::multimap<const Elem*,
std::pair<unsigned short int, short int> >::iterator >
e = _boundary_side_id.equal_range(elem);
// elem may be there, maybe multiple occurances
while (e.first != e.second)
{
// if this is true we found the requested side
// of the element and want to erase the requested id
if (e.first->second.first == side &&
e.first->second.second == id)
{
// (postfix++ - increment the iterator before it's invalid)
_boundary_side_id.erase(e.first++);
}
else
++e.first;
}
}
Definition at line 459 of file boundary_info.C.
References _boundary_side_id, and Elem::level().
{
libmesh_assert (elem != NULL);
// The user shouldn't be trying to remove only one child's boundary
// id
libmesh_assert (elem->level() == 0);
std::pair<std::multimap<const Elem*,
std::pair<unsigned short int, short int> >::iterator,
std::multimap<const Elem*,
std::pair<unsigned short int, short int> >::iterator >
e = _boundary_side_id.equal_range(elem);
// elem may be there, maybe multiple occurances
while (e.first != e.second)
{
// if this is true we found the requested side
// of the element and want to erase the id
if (e.first->second.first == side)
{
// (postfix++ - increment the iterator before it's invalid)
_boundary_side_id.erase(e.first++);
}
else
++e.first;
}
}
Returns invalid_uint if no side has the requested boundary id.
Definition at line 525 of file boundary_info.C.
References _boundary_side_id, libMesh::invalid_uint, Elem::level(), and Elem::top_parent().
{
const Elem* searched_elem = elem;
if (elem->level() != 0)
searched_elem = elem->top_parent();
std::pair<std::multimap<const Elem*,
std::pair<unsigned short int, short int> >::const_iterator,
std::multimap<const Elem*,
std::pair<unsigned short int, short int> >::const_iterator >
e = _boundary_side_id.equal_range(searched_elem);
// elem not in the data structure
if (e.first == e.second)
return libMesh::invalid_uint;
// elem is there, maybe multiple occurances
while (e.first != e.second)
{
// if this is true we found the requested boundary_id
// of the element and want to return the side
if (e.first->second.second == boundary_id)
return e.first->second.first;
++e.first;
}
// if we get here, we found elem in the data structure but not
// the requested boundary id, so return the default value
return libMesh::invalid_uint;
}
If you are using a MeshData class with this Mesh, you can pass a pointer to both the boundary_mesh's MeshData object, and the MeshData object used for this mesh.
Definition at line 204 of file boundary_info.C.
References _boundary_side_id, _mesh, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), ParallelMesh::add_elem(), ParallelMesh::add_point(), Elem::build_side(), ParallelMesh::clear(), DofObject::id(), Elem::n_nodes(), MeshBase::n_nodes(), ParallelMesh::n_nodes(), MeshBase::n_partitions(), Elem::n_sides(), MeshBase::n_subdomains(), Elem::neighbor(), Elem::node(), ParallelMesh::node_ptr(), MeshBase::nodes_begin(), MeshBase::nodes_end(), MeshBase::partitioner(), MeshBase::prepare_for_use(), DofObject::processor_id(), ParallelMesh::reserve_nodes(), AutoPtr< Tp >::reset(), MeshBase::set_n_partitions(), MeshBase::set_n_subdomains(), Elem::set_node(), Partitioner::set_node_processor_ids(), Elem::set_parent(), Elem::subdomain_id(), and Elem::top_parent().
{
// Re-create the boundary mesh.
boundary_mesh.clear();
boundary_mesh.set_n_subdomains() = _mesh.n_subdomains();
boundary_mesh.set_n_partitions() = _mesh.n_partitions();
// Make individual copies of all the nodes in the current mesh
// and add them to the boundary mesh. Yes, this is overkill because
// all of the current mesh nodes will not end up in the the boundary
// mesh. These nodes can be trimmed later via a call to prepare_for_use().
{
libmesh_assert (boundary_mesh.n_nodes() == 0);
boundary_mesh.reserve_nodes(_mesh.n_nodes());
MeshBase::const_node_iterator it = _mesh.nodes_begin();
MeshBase::const_node_iterator end = _mesh.nodes_end();
for(; it != end; ++it)
{
const Node* node = *it;
boundary_mesh.add_point(*node); // calls Node::build(Point, id)
}
}
// Add additional sides that aren't flagged with boundary conditions
MeshBase::const_element_iterator el = _mesh.active_elements_begin();
const MeshBase::const_element_iterator end_el = _mesh.active_elements_end();
for ( ; el != end_el; ++el)
{
const Elem* elem = *el;
for (unsigned int s=0; s<elem->n_sides(); s++)
if (elem->neighbor(s) == NULL) // on the boundary
{
// Get the top-level parent for this element
const Elem* top_parent = elem->top_parent();
// A convenient typedef
typedef
std::multimap<const Elem*, std::pair<unsigned short int, short int> >::const_iterator
Iter;
// Find all the bcs asociated with top_parent
std::pair<Iter, Iter> pos = _boundary_side_id.equal_range(top_parent);
// look for a bcid which is (i) in the user-requested set, and
// (ii) matches the current side #s
while (pos.first != pos.second)
{
// if this side is flagged with a boundary condition
// and the user wants this id
if ((pos.first->second.first == s) &&
(requested_boundary_ids.count(pos.first->second.second)))
{
// Build the side - do not use a 'proxy' element here:
// This will be going into the BoundaryMesh and needs to
// stand on its own.
AutoPtr<Elem> side (elem->build_side(s, false));
// inherit processor_id and subdomain_id from parent
side->subdomain_id() = elem->subdomain_id();
side->processor_id() = elem->processor_id();
// Add the side
Elem* new_elem = boundary_mesh.add_elem(side.release());
// and set the parent
new_elem->set_parent (const_cast<Elem*>(elem));
// This side's Node pointers still point to the nodes of the original mesh.
// We need to re-point them to the boundary mesh's nodes! Since we copied *ALL* of
// the original mesh's nodes over, we should be guaranteed to have the same ordering.
for (unsigned int nn=0; nn<new_elem->n_nodes(); ++nn)
{
// Get the correct node pointer, based on the id()
Node* new_node = boundary_mesh.node_ptr(new_elem->node(nn));
// sanity check: be sure that the new Nodes global id really matches
libmesh_assert (new_node->id() == new_elem->node(nn));
// Assign the new node pointer
new_elem->set_node(nn) = new_node;
}
// go on to the next side
break;
}
++pos.first;
} // end loop over bcs matching top_parent
} // end if neighbor is NULL
} // end loop over active elements
// Don't repartition this mesh; but rather inherit the partitioning
boundary_mesh.partitioner().reset(NULL);
// Trim any un-used nodes from the Mesh
boundary_mesh.prepare_for_use();
// and finally distribute element partitioning to the nodes
Partitioner::set_node_processor_ids(boundary_mesh);
}
If you are using a MeshData class with this Mesh, you can pass a pointer to both the boundary_mesh's MeshData object, and the MeshData object used for this mesh.
Re-create the boundary mesh.
Definition at line 66 of file boundary_info.C.
References _boundary_ids, _boundary_side_id, _mesh, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), ParallelMesh::add_elem(), ParallelMesh::add_point(), MeshData::assign(), Elem::build_side(), ParallelMesh::clear(), DofObject::id(), invalid_id, Elem::n_nodes(), MeshBase::n_nodes(), ParallelMesh::n_nodes(), Elem::n_sides(), Elem::neighbor(), Elem::node(), ParallelMesh::node_ptr(), MeshBase::nodes_begin(), MeshBase::nodes_end(), MeshBase::partitioner(), MeshBase::prepare_for_use(), ParallelMesh::reserve_nodes(), AutoPtr< Tp >::reset(), MeshBase::set_n_partitions(), MeshBase::set_n_subdomains(), Elem::set_node(), and Elem::top_parent().
{
boundary_mesh.clear();
// Map boundary ids to side subdomain/partition ids
std::map<short int, unsigned int> id_map;
// Original Code
// unsigned int cnt = 0;
// for (std::set<short int>::iterator pos = boundary_ids.begin();
// pos != boundary_ids.end(); ++pos)
// id_map[*pos] = cnt++;
// id_map[invalid_id] = cnt;
// New code
// Here we need to use iota() once it is in the
// Utility namespace.
std::for_each(_boundary_ids.begin(),
_boundary_ids.end(),
Fill(id_map));
boundary_mesh.set_n_subdomains() = id_map.size();
boundary_mesh.set_n_partitions() = id_map.size();
// Make individual copies of all the nodes in the current mesh
// and add them to the boundary mesh. Yes, this is overkill because
// all of the current mesh nodes will not end up in the the boundary
// mesh. These nodes can be trimmed later via a call to prepare_for_use().
{
libmesh_assert (boundary_mesh.n_nodes() == 0);
boundary_mesh.reserve_nodes(_mesh.n_nodes());
MeshBase::const_node_iterator it = _mesh.nodes_begin();
MeshBase::const_node_iterator end = _mesh.nodes_end();
for(; it != end; ++it)
{
const Node* node = *it;
boundary_mesh.add_point(*node); // calls Node::build(Point, id)
}
}
// Add additional sides that aren't flagged with boundary conditions
MeshBase::const_element_iterator el = _mesh.active_elements_begin();
const MeshBase::const_element_iterator end_el = _mesh.active_elements_end();
for ( ; el != end_el; ++el)
{
const Elem* elem = *el;
for (unsigned int s=0; s<elem->n_sides(); s++)
if (elem->neighbor(s) == NULL) // on the boundary
{
// Build the side - do not use a 'proxy' element here:
// This will be going into the BoundaryMesh and needs to
// stand on its own.
AutoPtr<Elem> side (elem->build_side(s, false));
// Get the top-level parent for this element
const Elem* top_parent = elem->top_parent();
// A convenient typedef
typedef
std::multimap<const Elem*, std::pair<unsigned short int, short int> >::const_iterator
Iter;
// Find the right id number for that side
std::pair<Iter, Iter> pos = _boundary_side_id.equal_range(top_parent);
while (pos.first != pos.second)
{
if (pos.first->second.first == s) // already flagged with a boundary condition
{
side->subdomain_id() =
id_map[pos.first->second.second];
break;
}
++pos.first;
}
// either the element wasn't found or side s
// doesn't have a boundary condition
if (pos.first == pos.second)
{
side->subdomain_id() = id_map[invalid_id];
}
side->processor_id() = side->subdomain_id(); //elem->processor_id();
// Add the side
Elem* new_elem = boundary_mesh.add_elem(side.release());
// This side's Node pointers still point to the nodes of the original mesh.
// We need to re-point them to the boundary mesh's nodes! Since we copied *ALL* of
// the original mesh's nodes over, we should be guaranteed to have the same ordering.
for (unsigned int nn=0; nn<new_elem->n_nodes(); ++nn)
{
// Get the correct node pointer, based on the id()
Node* new_node = boundary_mesh.node_ptr(new_elem->node(nn));
// sanity check: be sure that the new Nodes global id really matches
libmesh_assert (new_node->id() == new_elem->node(nn));
// Assign the new node pointer
new_elem->set_node(nn) = new_node;
}
}
} // end loop over active elements
// When desired, copy the MeshData
// to the boundary_mesh
if ((boundary_mesh_data != NULL) && (this_mesh_data != NULL))
boundary_mesh_data->assign(*this_mesh_data);
// Don't repartition this mesh; we're using the processor_id values
// as a hack to display bcids for now.
boundary_mesh.partitioner().reset(NULL);
// Trim any un-used nodes from the Mesh
boundary_mesh.prepare_for_use();
}
Definition at line 58 of file boundary_info.h.
Definition at line 280 of file boundary_info.h.
Referenced by add_node(), add_side(), clear(), get_boundary_ids(), n_boundary_ids(), and sync().
Definition at line 267 of file boundary_info.h.
Referenced by add_node(), boundary_ids(), build_node_boundary_ids(), build_node_list(), clear(), print_info(), and remove().
Definition at line 275 of file boundary_info.h.
Referenced by add_side(), boundary_id(), build_node_list_from_side_list(), build_side_boundary_ids(), build_side_list(), clear(), n_boundary_conds(), print_info(), remove(), remove_side(), side_with_boundary_id(), and sync().
Definition at line 260 of file boundary_info.h.
Referenced by add_node(), add_side(), n_boundary_conds(), and sync().
Definition at line 251 of file boundary_info.h.
Referenced by add_node(), add_side(), MeshTools::Modification::all_tri(), boundary_id(), MeshTools::Generation::build_cube(), MeshTools::Modification::flatten(), sync(), XdrIO::write_serialized_bcs(), and BoundaryInfo::Fill::~Fill().
Generated automatically by Doxygen for libMesh from the source code.