forked from idaholab/moose
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ParsedGenerateSideset.C
229 lines (198 loc) · 9.52 KB
/
ParsedGenerateSideset.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html
#include "ParsedGenerateSideset.h"
#include "Conversion.h"
#include "MooseMeshUtils.h"
#include "CastUniquePointer.h"
#include "libmesh/fparser_ad.hh"
#include "libmesh/distributed_mesh.h"
#include "libmesh/elem.h"
#include "libmesh/fe_base.h"
#include <typeinfo>
registerMooseObject("MooseApp", ParsedGenerateSideset);
InputParameters
ParsedGenerateSideset::validParams()
{
InputParameters params = SideSetsGeneratorBase::validParams();
params += FunctionParserUtils<false>::validParams();
params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
params.addRequiredParam<std::string>("combinatorial_geometry",
"Function expression encoding a combinatorial geometry");
params.addRequiredParam<BoundaryName>("new_sideset_name", "The name of the new sideset");
params.addParam<std::vector<BoundaryName>>(
"included_boundaries",
"A set of boundary names or ids whose sides will be included in the new sidesets");
params.addParam<std::vector<SubdomainName>>(
"included_subdomains",
"A set of subdomain names or ids whose sides will be included in the new sidesets");
params.addDeprecatedParam<std::vector<subdomain_id_type>>(
"included_subdomain_ids",
"A set of subdomain ids whose sides will be included in the new sidesets",
"included_subdomain_ids is deprecated, use included_subdomains with names or ids");
params.addParam<std::vector<SubdomainName>>("included_neighbors",
"A set of neighboring subdomain names or ids. A face "
"is only added if the subdomain id of the "
"neighbor is in this set");
params.addDeprecatedParam<std::vector<subdomain_id_type>>(
"included_neighbor_ids",
"A set of neighboring subdomain ids. A face is only added if the subdomain id of the "
"neighbor is in this set",
"included_neighbor_ids is deprecated, use included_neighbors with names or ids");
params.addParam<Point>(
"normal",
Point(),
"If provided specifies the normal vector on sides that are added to the new ");
params.addParam<std::vector<std::string>>("constant_names",
"Vector of constants used in the parsed function");
params.addParam<std::vector<std::string>>(
"constant_expressions",
"Vector of values for the constants in constant_names (can be an FParser expression)");
params.addClassDescription("A MeshGenerator that adds element sides to a sideset if the "
"centroid satisfies the `combinatorial_geometry` expression. "
"Optionally, element sides are also added if they are included in "
"`included_subdomain_ids` and if they feature the designated normal.");
return params;
}
ParsedGenerateSideset::ParsedGenerateSideset(const InputParameters & parameters)
: SideSetsGeneratorBase(parameters),
FunctionParserUtils<false>(parameters),
_input(getMesh("input")),
_function(parameters.get<std::string>("combinatorial_geometry")),
_sideset_name(getParam<BoundaryName>("new_sideset_name")),
_check_boundaries(isParamValid("included_boundaries")),
_check_subdomains(isParamValid("included_subdomain_ids") ||
isParamValid("included_subdomains")),
_check_neighbor_subdomains(isParamValid("included_neighbor_ids") ||
isParamValid("included_neighbors")),
_check_normal(parameters.isParamSetByUser("normal")),
_included_ids(isParamValid("included_subdomain_ids")
? parameters.get<std::vector<SubdomainID>>("included_subdomain_ids")
: std::vector<SubdomainID>()),
_included_neighbor_ids(isParamValid("included_neighbor_ids")
? parameters.get<std::vector<SubdomainID>>("included_neighbor_ids")
: std::vector<SubdomainID>()),
_normal(getParam<Point>("normal"))
{
// Handle deprecated parameters
if (isParamValid("included_subdomain_ids") && isParamValid("included_subdomains"))
paramError("included_subdomain_ids",
"included_subdomain_ids is deprecated, only specify included_subdomains");
if (isParamValid("included_neighbor_ids") && isParamValid("included_neighbors"))
paramError("included_neighbor_ids",
"included_neighbor_ids is deprecated, only specify included_neighbors");
// base function object
_func_F = std::make_shared<SymFunction>();
// set FParser internal feature flags
setParserFeatureFlags(_func_F);
// add the constant expressions
addFParserConstants(_func_F,
getParam<std::vector<std::string>>("constant_names"),
getParam<std::vector<std::string>>("constant_expressions"));
// parse function
if (_func_F->Parse(_function, "x,y,z") >= 0)
mooseError("Invalid function\n",
_function,
"\nin ParsedAddSideset ",
name(),
".\n",
_func_F->ErrorMsg());
_func_params.resize(3);
}
std::unique_ptr<MeshBase>
ParsedGenerateSideset::generate()
{
std::unique_ptr<MeshBase> mesh = std::move(_input);
if (!mesh->is_replicated())
mooseWarning(
"ParsedGenerateSideset is not implemented for distributed meshes. Make sure the "
"parsed sideset does NOT cross any mesh distribution boundaries, using the ProcessorAux");
setup(*mesh);
// Get a reference to our BoundaryInfo object for later use
BoundaryInfo & boundary_info = mesh->get_boundary_info();
// Get the boundary ids from the names
if (parameters().isParamValid("included_subdomains"))
{
// check that the subdomains exist in the mesh
const auto subdomains = getParam<std::vector<SubdomainName>>("included_subdomains");
for (const auto & name : subdomains)
if (!MooseMeshUtils::hasSubdomainName(*mesh, name))
paramError("included_subdomains", "The block '", name, "' was not found in the mesh");
_included_ids = MooseMeshUtils::getSubdomainIDs(*mesh, subdomains);
}
if (parameters().isParamValid("included_neighbors"))
{
// check that the subdomains exist in the mesh
const auto subdomains = getParam<std::vector<SubdomainName>>("included_neighbors");
for (const auto & name : subdomains)
if (!MooseMeshUtils::hasSubdomainName(*mesh, name))
paramError("included_neighbors", "The block '", name, "' was not found in the mesh");
_included_neighbor_ids = MooseMeshUtils::getSubdomainIDs(*mesh, subdomains);
}
std::vector<boundary_id_type> restricted_boundary_ids;
if (_check_boundaries)
restricted_boundary_ids = MooseMeshUtils::getBoundaryIDs(
*mesh, getParam<std::vector<BoundaryName>>("included_boundaries"), true);
// Get the BoundaryIDs from the mesh
std::vector<boundary_id_type> boundary_ids =
MooseMeshUtils::getBoundaryIDs(*mesh, {_sideset_name}, true);
mooseAssert(boundary_ids.size() == 1, "Length of boundary_ids should be one");
for (const auto & elem : mesh->active_element_ptr_range())
{
subdomain_id_type curr_subdomain = elem->subdomain_id();
// check if the element is included
if (_check_subdomains &&
std::find(_included_ids.begin(), _included_ids.end(), curr_subdomain) ==
_included_ids.end())
continue;
for (unsigned int side = 0; side < elem->n_sides(); ++side)
{
const std::vector<Point> & normals = _fe_face->get_normals();
_fe_face->reinit(elem, side);
// check if the neighboring elems subdomain is included
if (_check_neighbor_subdomains)
{
const Elem * neighbor = elem->neighbor_ptr(side);
// if the neighbor does not exist, then skip this face; we only add sidesets
// between existing elems if _check_neighbor_subdomains is true
if (!neighbor)
continue;
subdomain_id_type curr_neighbor_subdomain = neighbor->subdomain_id();
if (std::find(_included_neighbor_ids.begin(),
_included_neighbor_ids.end(),
curr_neighbor_subdomain) == _included_neighbor_ids.end())
continue;
}
// check normal if requested
if (_check_normal && std::abs(1.0 - _normal * normals[0]) > _variance)
continue;
// check that boundary is within the list of included boundaries
if (_check_boundaries)
{
bool in_included_boundaries = false;
for (auto bid : restricted_boundary_ids)
if (boundary_info.has_boundary_id(elem, side, bid))
in_included_boundaries = true;
if (!in_included_boundaries)
continue;
}
// check expression
std::unique_ptr<Elem> curr_side = elem->side_ptr(side);
_func_params[0] = curr_side->vertex_average()(0);
_func_params[1] = curr_side->vertex_average()(1);
_func_params[2] = curr_side->vertex_average()(2);
if (evaluate(_func_F))
boundary_info.add_side(elem, side, boundary_ids[0]);
}
}
finalize();
boundary_info.sideset_name(boundary_ids[0]) = _sideset_name;
boundary_info.nodeset_name(boundary_ids[0]) = _sideset_name;
mesh->set_isnt_prepared();
return dynamic_pointer_cast<MeshBase>(mesh);
}