www.mooseframework.org
SideSetsBetweenSubdomainsGenerator.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 
11 #include "InputParameters.h"
12 #include "MooseTypes.h"
13 #include "MooseMeshUtils.h"
14 #include "CastUniquePointer.h"
15 
16 #include "libmesh/remote_elem.h"
17 
19 
20 template <>
23 {
25 
26  params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
27  params.addRequiredParam<std::vector<SubdomainName>>(
28  "master_block", "The master set of blocks for which to draw a sideset between");
29  params.addRequiredParam<std::vector<SubdomainName>>(
30  "paired_block", "The paired set of blocks for which to draw a sideset between");
31  params.addRequiredParam<std::vector<BoundaryName>>("new_boundary",
32  "The name of the boundary to create");
33 
34  return params;
35 }
36 
38  const InputParameters & parameters)
39  : MeshGenerator(parameters), _input(getMesh("input"))
40 {
41 }
42 
43 std::unique_ptr<MeshBase>
45 {
46  std::unique_ptr<MeshBase> mesh = std::move(_input);
47 
48  std::vector<subdomain_id_type> vec_master_ids =
49  MooseMeshUtils::getSubdomainIDs(*mesh, getParam<std::vector<SubdomainName>>("master_block"));
50  std::set<subdomain_id_type> master_ids(vec_master_ids.begin(), vec_master_ids.end());
51 
52  std::vector<subdomain_id_type> vec_paired_ids =
53  MooseMeshUtils::getSubdomainIDs(*mesh, getParam<std::vector<SubdomainName>>("paired_block"));
54  std::set<subdomain_id_type> paired_ids(vec_paired_ids.begin(), vec_paired_ids.end());
55 
56  std::vector<BoundaryName> boundary_names = getParam<std::vector<BoundaryName>>("new_boundary");
57  std::vector<boundary_id_type> boundary_ids =
58  MooseMeshUtils::getBoundaryIDs(*mesh, boundary_names, true);
59 
60  // Get a reference to our BoundaryInfo object for later use
61  BoundaryInfo & boundary_info = mesh->get_boundary_info();
62 
63  // Prepare to query about sides adjacent to remote elements if we're
64  // on a distributed mesh
65  const processor_id_type my_n_proc = mesh->n_processors();
66  const processor_id_type my_proc_id = mesh->processor_id();
67  typedef std::vector<std::pair<dof_id_type, unsigned int>> vec_type;
68  std::vector<vec_type> queries(my_n_proc);
69 
70  for (const auto & elem : mesh->active_element_ptr_range())
71  {
72  subdomain_id_type curr_subdomain = elem->subdomain_id();
73 
74  // We only need to loop over elements in the master subdomain
75  if (master_ids.count(curr_subdomain) == 0)
76  continue;
77 
78  for (unsigned int side = 0; side < elem->n_sides(); side++)
79  {
80  const Elem * neighbor = elem->neighbor_ptr(side);
81 
82  // On a replicated mesh, we add all subdomain sides ourselves.
83  // On a distributed mesh, we may have missed sides which
84  // neighbor remote elements. We should query any such cases.
85  if (neighbor == remote_elem)
86  {
87  queries[elem->processor_id()].push_back(std::make_pair(elem->id(), side));
88  }
89  else if (neighbor != NULL && paired_ids.count(neighbor->subdomain_id()) > 0)
90 
91  // Add the boundaries
92  for (const auto & boundary_id : boundary_ids)
93  boundary_info.add_side(elem, side, boundary_id);
94  }
95  }
96 
97  if (!mesh->is_serial())
98  {
99  Parallel::MessageTag queries_tag = mesh->comm().get_unique_tag(867),
100  replies_tag = mesh->comm().get_unique_tag(5309);
101 
102  std::vector<Parallel::Request> side_requests(my_n_proc - 1), reply_requests(my_n_proc - 1);
103 
104  // Make all requests
105  for (processor_id_type p = 0; p != my_n_proc; ++p)
106  {
107  if (p == my_proc_id)
108  continue;
109 
110  Parallel::Request & request = side_requests[p - (p > my_proc_id)];
111 
112  mesh->comm().send(p, queries[p], request, queries_tag);
113  }
114 
115  // Reply to all requests
116  std::vector<vec_type> responses(my_n_proc - 1);
117 
118  for (processor_id_type p = 1; p != my_n_proc; ++p)
119  {
120  vec_type query;
121 
122  Parallel::Status status(mesh->comm().probe(Parallel::any_source, queries_tag));
123  const processor_id_type source_pid = cast_int<processor_id_type>(status.source());
124 
125  mesh->comm().receive(source_pid, query, queries_tag);
126 
127  Parallel::Request & request = reply_requests[p - 1];
128 
129  for (const auto & q : query)
130  {
131  const Elem * elem = mesh->elem_ptr(q.first);
132  const unsigned int side = q.second;
133  const Elem * neighbor = elem->neighbor_ptr(side);
134 
135  if (neighbor != NULL && paired_ids.count(neighbor->subdomain_id()) > 0)
136  {
137  responses[p - 1].push_back(std::make_pair(elem->id(), side));
138  }
139  }
140 
141  mesh->comm().send(source_pid, responses[p - 1], request, replies_tag);
142  }
143 
144  // Process all incoming replies
145  for (processor_id_type p = 1; p != my_n_proc; ++p)
146  {
147  Parallel::Status status(this->comm().probe(Parallel::any_source, replies_tag));
148  const processor_id_type source_pid = cast_int<processor_id_type>(status.source());
149 
150  vec_type response;
151 
152  this->comm().receive(source_pid, response, replies_tag);
153 
154  for (const auto & r : response)
155  {
156  const Elem * elem = mesh->elem_ptr(r.first);
157  const unsigned int side = r.second;
158 
159  for (const auto & boundary_id : boundary_ids)
160  boundary_info.add_side(elem, side, boundary_id);
161  }
162  }
163 
164  Parallel::wait(side_requests);
165  Parallel::wait(reply_requests);
166  }
167 
168  for (unsigned int i = 0; i < boundary_ids.size(); ++i)
169  boundary_info.sideset_name(boundary_ids[i]) = boundary_names[i];
170 
171  return dynamic_pointer_cast<MeshBase>(mesh);
172 }
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
These are reworked from https://stackoverflow.com/a/11003103.
std::vector< subdomain_id_type > getSubdomainIDs(const libMesh::MeshBase &mesh, const std::vector< SubdomainName > &subdomain_name)
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
Definition: MooseObject.h:191
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
registerMooseObject("MooseApp", SideSetsBetweenSubdomainsGenerator)
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
InputParameters validParams< SideSetsBetweenSubdomainsGenerator >()
SideSetsBetweenSubdomainsGenerator(const InputParameters &parameters)
std::vector< libMesh::boundary_id_type > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown)
MPI_Comm comm
InputParameters validParams< MeshGenerator >()
Definition: MeshGenerator.C:16
MeshGenerators are objects that can modify or add to an existing mesh.
Definition: MeshGenerator.h:30