www.mooseframework.org
SideSetsBetweenSubdomains.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 "MooseMesh.h"
14 
15 #include "libmesh/remote_elem.h"
16 
18 
19 template <>
22 {
24  params.addRequiredParam<std::vector<SubdomainName>>(
25  "master_block", "The master set of blocks for which to draw a sideset between");
26  params.addRequiredParam<std::vector<SubdomainName>>(
27  "paired_block", "The paired set of blocks for which to draw a sideset between");
28  params.addRequiredParam<std::vector<BoundaryName>>("new_boundary",
29  "The name of the boundary to create");
30  return params;
31 }
32 
34  : MeshModifier(parameters)
35 {
36 }
37 
38 void
40 {
41  MeshBase & mesh = _mesh_ptr->getMesh();
42 
43  std::vector<SubdomainID> vec_master_ids =
44  _mesh_ptr->getSubdomainIDs(getParam<std::vector<SubdomainName>>("master_block"));
45  std::set<SubdomainID> master_ids(vec_master_ids.begin(), vec_master_ids.end());
46 
47  std::vector<SubdomainID> vec_paired_ids =
48  _mesh_ptr->getSubdomainIDs(getParam<std::vector<SubdomainName>>("paired_block"));
49  std::set<SubdomainID> paired_ids(vec_paired_ids.begin(), vec_paired_ids.end());
50 
51  std::vector<BoundaryName> boundary_names = getParam<std::vector<BoundaryName>>("new_boundary");
52  std::vector<BoundaryID> boundary_ids = _mesh_ptr->getBoundaryIDs(boundary_names, true);
53 
54  // Get a reference to our BoundaryInfo object for later use
55  BoundaryInfo & boundary_info = mesh.get_boundary_info();
56 
57  // Prepare to query about sides adjacent to remote elements if we're
58  // on a distributed mesh
59  const processor_id_type my_n_proc = mesh.n_processors();
60  const processor_id_type my_proc_id = mesh.processor_id();
61  typedef std::vector<std::pair<dof_id_type, unsigned int>> vec_type;
62  std::vector<vec_type> queries(my_n_proc);
63 
64  for (const auto & elem : mesh.active_element_ptr_range())
65  {
66  SubdomainID curr_subdomain = elem->subdomain_id();
67 
68  // We only need to loop over elements in the master subdomain
69  if (master_ids.count(curr_subdomain) == 0)
70  continue;
71 
72  for (unsigned int side = 0; side < elem->n_sides(); side++)
73  {
74  const Elem * neighbor = elem->neighbor_ptr(side);
75 
76  // On a replicated mesh, we add all subdomain sides ourselves.
77  // On a distributed mesh, we may have missed sides which
78  // neighbor remote elements. We should query any such cases.
79  if (neighbor == remote_elem)
80  {
81  queries[elem->processor_id()].push_back(std::make_pair(elem->id(), side));
82  }
83  else if (neighbor != NULL && paired_ids.count(neighbor->subdomain_id()) > 0)
84 
85  // Add the boundaries
86  for (const auto & boundary_id : boundary_ids)
87  boundary_info.add_side(elem, side, boundary_id);
88  }
89  }
90 
91  if (!mesh.is_serial())
92  {
93  Parallel::MessageTag queries_tag = mesh.comm().get_unique_tag(867),
94  replies_tag = mesh.comm().get_unique_tag(5309);
95 
96  std::vector<Parallel::Request> side_requests(my_n_proc - 1), reply_requests(my_n_proc - 1);
97 
98  // Make all requests
99  for (processor_id_type p = 0; p != my_n_proc; ++p)
100  {
101  if (p == my_proc_id)
102  continue;
103 
104  Parallel::Request & request = side_requests[p - (p > my_proc_id)];
105 
106  mesh.comm().send(p, queries[p], request, queries_tag);
107  }
108 
109  // Reply to all requests
110  std::vector<vec_type> responses(my_n_proc - 1);
111 
112  for (processor_id_type p = 1; p != my_n_proc; ++p)
113  {
114  vec_type query;
115 
116  Parallel::Status status(mesh.comm().probe(Parallel::any_source, queries_tag));
117  const processor_id_type source_pid = cast_int<processor_id_type>(status.source());
118 
119  mesh.comm().receive(source_pid, query, queries_tag);
120 
121  Parallel::Request & request = reply_requests[p - 1];
122 
123  for (const auto & q : query)
124  {
125  const Elem * elem = mesh.elem_ptr(q.first);
126  const unsigned int side = q.second;
127  const Elem * neighbor = elem->neighbor_ptr(side);
128 
129  if (neighbor != NULL && paired_ids.count(neighbor->subdomain_id()) > 0)
130  {
131  responses[p - 1].push_back(std::make_pair(elem->id(), side));
132  }
133  }
134 
135  mesh.comm().send(source_pid, responses[p - 1], request, replies_tag);
136  }
137 
138  // Process all incoming replies
139  for (processor_id_type p = 1; p != my_n_proc; ++p)
140  {
141  Parallel::Status status(this->comm().probe(Parallel::any_source, replies_tag));
142  const processor_id_type source_pid = cast_int<processor_id_type>(status.source());
143 
144  vec_type response;
145 
146  this->comm().receive(source_pid, response, replies_tag);
147 
148  for (const auto & r : response)
149  {
150  const Elem * elem = mesh.elem_ptr(r.first);
151  const unsigned int side = r.second;
152 
153  for (const auto & boundary_id : boundary_ids)
154  boundary_info.add_side(elem, side, boundary_id);
155  }
156  }
157 
158  Parallel::wait(side_requests);
159  Parallel::wait(reply_requests);
160  }
161 
162  for (unsigned int i = 0; i < boundary_ids.size(); ++i)
163  boundary_info.sideset_name(boundary_ids[i]) = boundary_names[i];
164 }
MeshModifiers are objects that can modify or add to an existing mesh.
Definition: MeshModifier.h:25
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
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...
MooseMesh * _mesh_ptr
Pointer to the mesh.
Definition: MeshModifier.h:68
virtual void modify() override
Pure virtual modify function MUST be overridden by children classes.
SideSetsBetweenSubdomains(const InputParameters &parameters)
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:2567
subdomain_id_type SubdomainID
registerMooseObject("MooseApp", SideSetsBetweenSubdomains)
InputParameters validParams< SideSetsBetweenSubdomains >()
MPI_Comm comm
std::vector< BoundaryID > getBoundaryIDs(const Elem *const elem, const unsigned short int side) const
Returns a vector of boundary IDs for the requested element on the requested side. ...
Definition: MooseMesh.C:2153
std::vector< SubdomainID > getSubdomainIDs(const std::vector< SubdomainName > &subdomain_name) const
Get the associated subdomainIDs for the subdomain names that are passed in.
Definition: MooseMesh.C:1090
InputParameters validParams< MeshModifier >()
Definition: MeshModifier.C:15