https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ComponentJunction.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
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// MOOSE includes
11#include "ComponentJunction.h"
12#include "MooseUtils.h"
13
14registerMooseAction("MooseApp", ComponentJunction, "add_mesh_generator");
15// ComponentJunction is an example of ComponentPhysicsInterface
16registerMooseAction("MooseApp", ComponentJunction, "init_component_physics");
17// ComponentJunction is an example of ComponentMaterialPropertyInterface
18registerMooseAction("MooseApp", ComponentJunction, "add_material");
19// ComponentJunction is an example of ComponentInitialConditionInterface
20registerMooseAction("MooseApp", ComponentJunction, "check_integrity");
22
25{
31
32 params.addClassDescription("Component to join two other components.");
33
34 params.addRequiredParam<ComponentName>("first_component", "First component to join");
35 params.addRequiredParam<BoundaryName>("first_boundary", "First boundary to connect to.");
36 params.addRequiredParam<ComponentName>("second_component", "Second component to join");
37 params.addRequiredParam<BoundaryName>("second_boundary", "Second boundary to connect to.");
38
39 MooseEnum junction_type("stitch_meshes extrude_boundary", "extrude_boundary");
40 params.addParam<MooseEnum>("junction_method", junction_type, "How to join the two components");
41
42 /* Stitching parameters */
43 params.addParam<bool>("enforce_all_nodes_match_on_boundaries",
44 true,
45 "Only stitch if all nodes match on the boundary. Defaults to true because "
46 "there is a search algorithm that forces nodes to match assuming there are "
47 "equal number of nodes on each target boundary.");
48
49 /* Meshing the gap parameters */
50 // Parameters for the region between meshes
51 params.addParam<unsigned int>("n_elem_normal",
52 "Number of elements in the normal direction of the junction");
53 params.addParam<SubdomainName>("block", "Block name for the junction, if a block is created.");
54
55 // Parameters for changing radius -- final radius will be calculated under the hood
56 MooseEnum radial_growth_methods("LINEAR CUBIC", "CUBIC");
57 params.addParam<MooseEnum>("radial_growth_method",
58 radial_growth_methods,
59 "Functional form to change radius while extruding along curve.");
60 params.addParam<Real>("start_radial_growth_rate", 0, "Starting rate of radial expansion.");
61 params.addParam<Real>("end_radial_growth_rate", 0, "Ending rate of radial expansion.");
62
63 // Parameters for the 1D spline joining the two components (serving as an extrusion guide for
64 // 2,3D)
65 params.addRangeCheckedParam<libMesh::Real>("sharpness",
66 "sharpness>0 & sharpness<=1",
67 "Sharpness of curve bend. See BSplineCurveGenerator "
68 "for explanation of the meaning given to sharpness");
69 params.addParam<unsigned int>(
70 "num_cps",
71 6,
72 "Number of control points used to draw the curve. Miniumum of degree+1 points are required.");
73 MooseEnum edge_elem_type("EDGE2 EDGE3 EDGE4", "EDGE2");
74 params.addParam<MooseEnum>(
75 "edge_element_type", edge_elem_type, "Type of the EDGE elements to be generated.");
76
77 params.addParamNamesToGroup("sharpness num_cps edge_element_type", "1D mesh junction");
79 "radial_growth_method start_radial_growth_rate end_radial_growth_rate",
80 "Radial expansion in 2D and 3D junction");
81
82 return params;
83}
84
86 : ActionComponent(params),
91 _junction_method(getParam<MooseEnum>("junction_method")),
92 _enforce_all_nodes_match_on_boundaries(getParam<bool>("enforce_all_nodes_match_on_boundaries"))
93{
94 addRequiredTask("add_mesh_generator");
95
96 // Check parameters
97 if (_junction_method != "extrude_boundary")
98 errorDependentParameter("junction_method",
99 "extrude_boundary",
100 {"n_elem_normal",
101 "block",
102 "radial_growth_method",
103 "start_radial_growth_rate",
104 "end_radial_growth_rate",
105 "sharpness",
106 "num_cps",
107 "edge_element_type"});
108 else
109 {
110 if (!isParamValid("n_elem_normal"))
111 paramError("n_elem_normal", "Should be specified if junction_method = 'extrude_boundary'");
112 }
113 // The 1D and 2D meshing parameters will be re-checked later, once we know the dimension
114}
115
116void
118{
119 auto & first_component =
120 _awh.getAction<ActionComponent>(getParam<ComponentName>("first_component"));
121 auto & second_component =
122 _awh.getAction<ActionComponent>(getParam<ComponentName>("second_component"));
123 const auto first_boundary = getParam<BoundaryName>("first_boundary");
124 const auto second_boundary = getParam<BoundaryName>("second_boundary");
125
126 // Get the dimension of the components
127 const auto dimension_first = first_component.dimension();
128 const auto dimension_second = second_component.dimension();
129
130 if (dimension_first == 0 || dimension_second == 0)
131 mooseError("Connecting 0 dimension meshes not implemented!");
132
133 // Perform junction
134 if (_junction_method == "stitch_meshes")
135 {
136 // Fairly easy to stitch this
137 if (dimension_first == dimension_second)
138 {
139 if (first_component.getCurrentTopLevelMeshGeneratorName() !=
140 second_component.getCurrentTopLevelMeshGeneratorName())
141 { // Stitch the two meshes
142 InputParameters params = _factory.getValidParams("StitchMeshGenerator");
143 params.set<std::vector<MeshGeneratorName>>("inputs") = {
144 first_component.getCurrentTopLevelMeshGeneratorName(),
145 second_component.getCurrentTopLevelMeshGeneratorName()};
146 params.set<std::vector<std::vector<std::string>>>("stitch_boundaries_pairs") = {
147 {first_boundary, second_boundary}};
148 params.set<bool>("verbose_stitching") = _verbose;
149 params.set<bool>("enforce_all_nodes_match_on_boundaries") =
152 "StitchMeshGenerator", name() + "_base", params);
153 _mg_names.push_back(name() + "_base");
154 }
155 else
156 {
157 // Handles case of needing to close a mesh. Using StitchBoundaryMeshGenerator prevents
158 // issues with element overlap.
159 InputParameters params = _factory.getValidParams("StitchBoundaryMeshGenerator");
160 params.set<MeshGeneratorName>("input") =
161 first_component.getCurrentTopLevelMeshGeneratorName();
162 params.set<std::vector<std::vector<std::string>>>("stitch_boundaries_pairs") = {
163 {first_boundary, second_boundary}};
164 params.set<bool>("show_info") = _verbose;
166 "StitchBoundaryMeshGenerator", name() + "_close", params);
167 _mg_names.push_back(name() + "_close");
168 }
169 }
170 else
171 mooseError("Stiching meshes of different dimensions is not implemented");
172 }
173
174 else if (_junction_method == "extrude_boundary")
175 {
176 //
177 // This junction method is set to use a B-Spline to draw a 1D curve between, then extrude along
178 // that spline
179 //
180
181 // find start and end directions (may need to take the negative of the end direction).
182 // obey user parameters if set
183 // TODO: modify the spline curve generator to figure out the direction so we can support other
184 // component types
185 // TODO: this really should be the surface direction, not the component direction. Maybe all
186 // this should be deleted and replaced by logic in the Spline curve generator instead.
187 auto get_direction = [this](const auto & component, const auto & param_name) -> RealVectorValue
188 {
189 const auto & cname = component.name();
190 if (dynamic_cast<const ComponentMeshTransformHelper *>(
193 else if (component.isParamValid("direction"))
194 return component.template getParam<RealVectorValue>("direction");
195 else
196 paramError(param_name,
197 "Only components inheriting from 'ComponentMeshTransformerHelper' or with a "
198 "'direction' parameter are supported at this time");
199 };
200
201 RealVectorValue start_direction = get_direction(first_component, "first_component");
202 RealVectorValue end_direction = get_direction(second_component, "second_component");
203
204 InputParameters bspline_params = _factory.getValidParams("BSplineCurveGenerator");
205 bspline_params.set<RealVectorValue>("start_direction") = start_direction;
206 bspline_params.set<RealVectorValue>("end_direction") = -end_direction;
207 bspline_params.set<unsigned int>("num_elements") = getParam<unsigned int>("n_elem_normal");
208 if (isParamValid("sharpness"))
209 bspline_params.set<Real>("sharpness") = getParam<Real>("sharpness");
210 bspline_params.set<unsigned int>("num_cps") = getParam<unsigned int>("num_cps");
211 bspline_params.set<MeshGeneratorName>("start_mesh") =
212 first_component.meshGeneratorNames().back();
213 bspline_params.set<MeshGeneratorName>("end_mesh") =
214 second_component.meshGeneratorNames().back();
215 bspline_params.set<BoundaryName>("boundary_providing_start_point") =
216 getParam<BoundaryName>("first_boundary");
217 bspline_params.set<BoundaryName>("boundary_providing_end_point") =
218 getParam<BoundaryName>("second_boundary");
219
220 if (dimension_first == 1)
221 {
222 if (isParamValid("block"))
223 bspline_params.set<SubdomainName>("new_subdomain_name") = getParam<SubdomainName>("block");
224 bspline_params.set<std::vector<BoundaryName>>("edge_nodesets") = {
225 name() + "_bspline_start_node", name() + "_bspline_end_node"};
226 bspline_params.set<bool>("output") = _verbose;
227 }
228
230 "BSplineCurveGenerator", name() + "_curve", bspline_params);
231 _mg_names.push_back(name() + "_curve");
232
233 // Extrude boundary from first component
234 if (dimension_first > 1)
235 {
236 // create lower dimension mesh on the boundary
237 InputParameters ld_source_params = _factory.getValidParams("LowerDBlockFromSidesetGenerator");
238 ld_source_params.set<MeshGeneratorName>("input") =
239 first_component.meshGeneratorNames().back();
240 ld_source_params.set<std::vector<BoundaryName>>("sidesets") =
241 std::vector{getParam<BoundaryName>("first_boundary")};
242 ld_source_params.set<SubdomainName>("new_block_name") =
243 (SubdomainName)(name() + "_LowerDBlockSource");
245 "LowerDBlockFromSidesetGenerator", name() + "_lowerDGenerationSource", ld_source_params);
246 _mg_names.push_back(name() + "_lowerDGenerationSource");
247
248 InputParameters _bmc_source_params = _factory.getValidParams("BlockToMeshConverterGenerator");
249 _bmc_source_params.set<MeshGeneratorName>("input") = name() + "_lowerDGenerationSource";
250 _bmc_source_params.set<std::vector<SubdomainName>>("target_blocks") = {
251 (SubdomainName)(name() + "_LowerDBlockSource")};
253 "BlockToMeshConverterGenerator", name() + "_blockToMeshSource", _bmc_source_params);
254 _mg_names.push_back(name() + "_blockToMeshSource");
255
256 // set up AdvancedExtruderGenerator
257 InputParameters aeg_params = _factory.getValidParams("AdvancedExtruderGenerator");
258 aeg_params.set<MeshGeneratorName>("extrusion_curve") = (MeshGeneratorName)(name() + "_curve");
259 aeg_params.set<MeshGeneratorName>("input") =
260 (MeshGeneratorName)(name() + "_blockToMeshSource");
261
262 aeg_params.set<RealVectorValue>("start_extrusion_direction") = start_direction;
263 aeg_params.set<RealVectorValue>("end_extrusion_direction") = end_direction;
264
265 aeg_params.set<Real>("start_radial_growth_rate") = getParam<Real>("start_radial_growth_rate");
266 aeg_params.set<Real>("end_radial_growth_rate") = getParam<Real>("end_radial_growth_rate");
267 aeg_params.set<MooseEnum>("radial_growth_method") =
268 getParam<MooseEnum>("radial_growth_method");
269
270 aeg_params.set<BoundaryName>("bottom_boundary") = name() + "_aeg_bottom_boundary";
271 aeg_params.set<BoundaryName>("top_boundary") = name() + "_aeg_top_boundary";
272 if (isParamValid("block"))
273 paramError("block", "Not yet implemented for 2D or 3D junction");
274 aeg_params.set<bool>("output") = _verbose;
275
277 "AdvancedExtruderGenerator", name() + "_aeg", aeg_params);
278 _mg_names.push_back(name() + "_aeg");
279 }
280
281 // Stitch the extrusion / curve (in 1D) to the components
282 if (first_component.getCurrentTopLevelMeshGeneratorName() !=
283 second_component.getCurrentTopLevelMeshGeneratorName())
284 {
285 InputParameters stitcher_params = _factory.getValidParams("StitchMeshGenerator");
286 stitcher_params.set<std::vector<MeshGeneratorName>>("inputs") =
287 std::vector<MeshGeneratorName>{first_component.getCurrentTopLevelMeshGeneratorName(),
288 _mg_names.back(),
289 second_component.getCurrentTopLevelMeshGeneratorName()};
290 if (dimension_first > 1)
291 stitcher_params.set<std::vector<std::vector<std::string>>>("stitch_boundaries_pairs") = {
292 {first_boundary, name() + "_aeg_bottom_boundary"},
293 {name() + "_aeg_top_boundary", second_boundary}};
294 else
295 {
296 stitcher_params.set<bool>("clear_stitched_boundary_ids") = false;
297 stitcher_params.set<std::vector<std::vector<std::string>>>("stitch_boundaries_pairs") = {
298 {first_boundary, name() + "_bspline_start_node"},
299 {name() + "_bspline_end_node", second_boundary}};
300 }
301
302 stitcher_params.set<bool>("verbose_stitching") = _verbose;
303 stitcher_params.set<bool>("output") = _verbose;
304 stitcher_params.set<bool>("enforce_all_nodes_match_on_boundaries") =
307 "StitchMeshGenerator", name() + "_stitcher", stitcher_params);
308 _mg_names.push_back(name() + "_stitcher");
309 }
310 else
311 {
312 // Handles case of needing to close a mesh. Using StitchBoundaryMeshGenerator prevents
313 // issues with element overlap.
314 InputParameters mesh_stitcher_params = _factory.getValidParams("StitchMeshGenerator");
315 mesh_stitcher_params.set<std::vector<MeshGeneratorName>>("inputs") =
316 std::vector<MeshGeneratorName>{first_component.getCurrentTopLevelMeshGeneratorName(),
317 _mg_names.back()};
318 if (dimension_first > 1)
319 mesh_stitcher_params.set<std::vector<std::vector<std::string>>>(
320 "stitch_boundaries_pairs") = {{first_boundary, name() + "_aeg_bottom_boundary"}};
321 else
322 mesh_stitcher_params.set<std::vector<std::vector<std::string>>>(
323 "stitch_boundaries_pairs") = {{first_boundary, name() + "_bspline_start_node"}};
324 mesh_stitcher_params.set<bool>("verbose_stitching") = _verbose;
325 // TODO: remove this once we understand why it errors without
326 mesh_stitcher_params.set<bool>("clear_stitched_boundary_ids") = false;
327 mesh_stitcher_params.set<bool>("enforce_all_nodes_match_on_boundaries") =
330 "StitchMeshGenerator", name() + "_mesh_stitcher", mesh_stitcher_params);
331 _mg_names.push_back(name() + "_stitcher");
332
333 InputParameters boundary_stitcher_params =
334 _factory.getValidParams("StitchBoundaryMeshGenerator");
335 boundary_stitcher_params.set<MeshGeneratorName>("input") = name() + "_mesh_stitcher";
336 if (dimension_first > 1)
337 boundary_stitcher_params.set<std::vector<std::vector<std::string>>>(
338 "stitch_boundaries_pairs") = {{name() + "_aeg_top_boundary", second_boundary}};
339 else
340 boundary_stitcher_params.set<std::vector<std::vector<std::string>>>(
341 "stitch_boundaries_pairs") = {{name() + "_bspline_end_node", second_boundary}};
342 boundary_stitcher_params.set<bool>("show_info") = _verbose;
344 "StitchBoundaryMeshGenerator", name() + "_closed", boundary_stitcher_params);
345 _mg_names.push_back(name() + "_closed");
346 }
347 }
348 else
349 mooseError("junction_method specified is invalid!");
350
351 _top_mg_name = _mg_names.back();
352 first_component.addConnectedComponent(second_component);
353 // Sets it for all connected components
354 // Connected might not be the right abstraction here. It's more like "included in a common mesh"
355 for (auto * component : first_component.getConnectedComponents())
356 component->setCurrentTopLevelMeshGeneratorName(_top_mg_name);
357
358 // For now this is a safe choice. We might want to decide otherwise once we
359 // do mixed-dimensions. Build the junction with the dimension of the first component?
360 mooseAssert(dimension_first == dimension_second, "Should be the same");
361 _dimension = std::max(dimension_first, dimension_second);
362}
363
364void
registerActionComponent("MooseApp", ComponentJunction)
registerMooseAction("MooseApp", ComponentJunction, "add_mesh_generator")
Base class for components that are defined using an action.
const std::vector< MeshGeneratorName > & meshGeneratorNames() const
Get the name(s) of the mesh generator(s) created by this component that generates the mesh for it.
std::vector< MeshGeneratorName > _mg_names
Name(s) of the final mesh generator(s) creating the mesh for the component.
void addRequiredTask(const std::string &task)
Add a new required task for all physics deriving from this class NOTE: This does not register the tas...
const bool _verbose
Whether the component setup should be verbose.
MeshGeneratorName _top_mg_name
Name of the top-most mesh generator in the hierarchy of MGs on top of the ones generating this compon...
static InputParameters validParams()
unsigned int _dimension
Maximum dimension of the component.
MeshGeneratorName getCurrentTopLevelMeshGeneratorName() const
Return the name of the final mesh generator that contains this component This may not be one of the m...
unsigned int dimension() const
Return the dimension of the component.
const T & getAction(const std::string &name) const
Retrieve an action with its name and the desired type.
MooseApp & _app
The MOOSE application this is associated with.
Definition MooseBase.h:375
ActionWarehouse & _awh
Reference to ActionWarehouse where we store object build by actions.
Definition Action.h:169
Helper class to help Components accept boundary condition parameters that the Physics may use to gene...
virtual void checkIntegrity() override
Used for various checks notably:
Helper class to help Components define the initial conditions the Physics may need from the parameter...
virtual void checkIntegrity() override
Used for various checks notably:
ActionComponent to connect two components.
virtual void addMeshGenerators() override
static InputParameters validParams()
virtual void checkIntegrity() override
Used for various checks notably:
ComponentJunction(const InputParameters &params)
bool _enforce_all_nodes_match_on_boundaries
Whether to enforce that all nodes match on a boundary when stitching them.
const MooseEnum _junction_method
How to connect the two components.
Helper class to help Components define the material properties the Physics may need from the paramete...
Helper class to help Components be located with the orientation and position we want.
RealVectorValue direction() const
Return the direction (axis for a cylinder for example) of the component.
Helper class to help creating an entire physics Note: Trying out virtual inheritance.
static InputParameters validParams()
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
Definition Factory.C:68
void errorDependentParameter(const std::string &param1, const std::string &value_not_set, const std::vector< std::string > &dependent_params) const
Error messages for parameters that should depend on another parameter.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
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...
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.
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
void addMeshGenerator(const std::string &type, const std::string &name, const InputParameters &params)
Add a mesh generator that will act on the meshes in the system.
MeshGeneratorSystem & getMeshGeneratorSystem()
Gets the system that manages the MeshGenerators.
Definition MooseApp.h:886
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition MooseBase.h:457
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition MooseBase.h:271
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
Factory & _factory
The Factory associated with the MooseApp.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real