www.mooseframework.org
BreakMeshByBlock.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "BreakMeshByBlock.h"
11 #include "MooseMesh.h"
12 
13 #include "libmesh/elem.h"
14 
16 
17 template <>
20 {
22  params.addClassDescription("Break boundaries based on the subdomains to which their sides are "
23  "attached. Naming convention for the new boundaries will be the old "
24  "boundary name plus \"_to_\" plus the subdomain name. At the moment"
25  "this only works on REPLICATED mesh");
26  return params;
27 }
28 
30  : BreakMeshByBlockBase(parameters)
31 {
32 }
33 
34 void
36 {
37 
38  // TODO remove when distributed MESH capabilities are implemented
39  _mesh_ptr->errorIfDistributedMesh("BreakMeshByBlock only works on a REPLICATED mesh");
41 
42  // save reference to mesh
43  MeshBase & mesh = _mesh_ptr->getMesh();
44 
45  // initialize the node to elemen map
46  const auto & node_to_elem_map = _mesh_ptr->nodeToElemMap();
47 
48  for (auto node_it = node_to_elem_map.begin(); node_it != node_to_elem_map.end(); ++node_it)
49  {
50  const dof_id_type current_node_id = node_it->first;
51  const Node * current_node = mesh.node_ptr(current_node_id);
52 
53  if (current_node != nullptr)
54  {
55  // find node multiplicity
56  const std::set<SubdomainID> & connected_blocks = _mesh_ptr->getNodeBlockIds(*current_node);
57  unsigned int node_multiplicity = connected_blocks.size();
58 
59  // check if current_node need to be duplicated
60  if (node_multiplicity > 1)
61  {
62  // retrieve connected elements from the map
63  const std::vector<dof_id_type> & connected_elems = node_it->second;
64 
65  // find reference_subdomain_id (e.g. the subdomain with lower id)
66  auto subdomain_it = connected_blocks.begin();
67  SubdomainID reference_subdomain_id = *subdomain_it;
68 
69  // multiplicity counter to keep track of how many nodes we added
70  unsigned int multiplicity_counter = node_multiplicity;
71  for (auto elem_id : connected_elems)
72  {
73  // all the duplicate nodes are added and assigned
74  if (multiplicity_counter == 0)
75  break;
76 
77  Elem * current_elem = mesh.elem_ptr(elem_id);
78  if (current_elem->subdomain_id() != reference_subdomain_id)
79  {
80  // assign the newly added node to current_elem
81  Node * new_node = nullptr;
82 
83  for (unsigned int node_id = 0; node_id < current_elem->n_nodes(); ++node_id)
84  if (current_elem->node_id(node_id) ==
85  current_node->id()) // if current node == node on element
86  {
87  // add new node
88  new_node = Node::build(*current_node, mesh.n_nodes()).release();
89  new_node->processor_id() = current_node->processor_id();
90  mesh.add_node(new_node);
91 
92  // Add boundary info to the new node
93  std::vector<boundary_id_type> node_boundary_ids =
94  mesh.boundary_info->boundary_ids(current_node);
95  mesh.boundary_info->add_node(new_node, node_boundary_ids);
96 
97  multiplicity_counter--; // node created, update multiplicity counter
98 
99  current_elem->set_node(node_id) = new_node;
100  break; // ones the proper node has been fixed in one element we can break the
101  // loop
102  }
103 
104  for (auto connected_elem_id : connected_elems)
105  {
106  Elem * connected_elem = mesh.elem_ptr(connected_elem_id);
107 
108  // Assign the newly added node to other connected elements with the same block_id
109  if (connected_elem->subdomain_id() == current_elem->subdomain_id() &&
110  connected_elem != current_elem)
111  {
112  for (unsigned int node_id = 0; node_id < connected_elem->n_nodes(); ++node_id)
113  if (connected_elem->node_id(node_id) ==
114  current_node->id()) // if current node == node on element
115  {
116  connected_elem->set_node(node_id) = new_node;
117  break;
118  }
119  }
120  }
121  }
122  }
123 
124  // create blocks pair and assign element side to new interface boundary map
125  for (auto elem_id : connected_elems)
126  {
127  for (auto connected_elem_id : connected_elems)
128  {
129  Elem * current_elem = mesh.elem_ptr(elem_id);
130  Elem * connected_elem = mesh.elem_ptr(connected_elem_id);
131 
132  if (current_elem != connected_elem &&
133  current_elem->subdomain_id() < connected_elem->subdomain_id())
134  {
135  if (current_elem->has_neighbor(connected_elem))
136  {
137  std::pair<subdomain_id_type, subdomain_id_type> blocks_pair =
138  std::make_pair(current_elem->subdomain_id(), connected_elem->subdomain_id());
139 
140  _new_boundary_sides_map[blocks_pair].insert(std::make_pair(
141  current_elem->id(), current_elem->which_neighbor_am_i(connected_elem)));
142  }
143  }
144  }
145  }
146 
147  } // end multiplicity check
148  } // end loop over nodes
149  } // end nodeptr check
150 
152 }
153 
154 void
156 {
157  BoundaryInfo & boundary_info = _mesh_ptr->getMesh().get_boundary_info();
158 
159  BoundaryID boundaryID = findFreeBoundaryId();
160  std::string boundaryName = _interface_name;
161 
162  // loop over boundary sides
163  for (auto & boundary_side_map : _new_boundary_sides_map)
164  {
165 
166  // find the appropriate boundary name and id
167  // given master and slave block ID
168  if (_split_interface)
169  findBoundaryNameAndInd(boundary_side_map.first.first,
170  boundary_side_map.first.second,
171  boundaryName,
172  boundaryID,
173  boundary_info);
174  else
175  boundary_info.sideset_name(boundaryID) = boundaryName;
176 
177  // loop over all the side belonging to each pair and add it to the proper interface
178  for (auto & element_side : boundary_side_map.second)
179  boundary_info.add_side(element_side.first, element_side.second, boundaryID);
180  }
181 }
InputParameters validParams< BreakMeshByBlockBase >()
InputParameters validParams< BreakMeshByBlock >()
std::string _interface_name
the name of the new interface
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
const std::set< SubdomainID > & getNodeBlockIds(const Node &node) const
Return list of blocks to which the given node belongs.
Definition: MooseMesh.C:847
bool _split_interface
the flag to split the interface by block
std::map< std::pair< subdomain_id_type, subdomain_id_type >, std::set< std::pair< dof_id_type, unsigned int > > > _new_boundary_sides_map
MooseMesh * _mesh_ptr
Pointer to the mesh.
Definition: MeshModifier.h:68
void errorIfDistributedMesh(std::string name) const
Generate a unified error message if the underlying libMesh mesh is a DistributedMesh.
Definition: MooseMesh.C:2685
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:2567
BoundaryID findFreeBoundaryId()
this method finds the first free boundary id
void checkInputParameter()
check that if split_interface==true interface_id and interface_name are not set by the user...
boundary_id_type BoundaryID
registerMooseObject("MooseApp", BreakMeshByBlock)
subdomain_id_type SubdomainID
BreakMeshByBlock(const InputParameters &parameters)
void addInterfaceBoundary()
generate the new boundary interface
virtual void modify() override
Pure virtual modify function MUST be overridden by children classes.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
void findBoundaryNameAndInd(const subdomain_id_type &, const subdomain_id_type &, std::string &, BoundaryID &, BoundaryInfo &)
given the master and slave blocks this method return the appropriate boundary id and name ...
const std::map< dof_id_type, std::vector< dof_id_type > > & nodeToElemMap()
If not already created, creates a map from every node to all elements to which they are connected...
Definition: MooseMesh.C:690