Line data Source code
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 : #include "FillBetweenCurvesGenerator.h"
11 : #include "FillBetweenPointVectorsTools.h"
12 :
13 : #include "CastUniquePointer.h"
14 : #include "libmesh/node.h"
15 :
16 : registerMooseObject("MooseApp", FillBetweenCurvesGenerator);
17 :
18 : InputParameters
19 14305 : FillBetweenCurvesGenerator::validParams()
20 : {
21 14305 : InputParameters params = MeshGenerator::validParams();
22 14305 : params.addRequiredParam<MeshGeneratorName>("input_mesh_1",
23 : "The input mesh that contains curve 1");
24 14305 : params.addRequiredParam<MeshGeneratorName>("input_mesh_2",
25 : "The input mesh that contains curve 1");
26 42915 : params.addParam<Point>(
27 28610 : "mesh_1_shift", Point(0.0, 0.0, 0.0), "Translation vector to be applied to input_mesh_1");
28 42915 : params.addParam<Point>(
29 28610 : "mesh_2_shift", Point(0.0, 0.0, 0.0), "Translation vector to be applied to input_mesh_2");
30 14305 : params.addRequiredRangeCheckedParam<unsigned int>(
31 : "num_layers", "num_layers>0", "Number of layers of elements created between the boundaries.");
32 14305 : params.addParam<subdomain_id_type>("block_id", 1, "ID to be assigned to the transition layer.");
33 42915 : params.addParam<boundary_id_type>(
34 : "input_boundary_1_id",
35 28610 : 10000,
36 : "Boundary ID to be assigned to the boundary defined by positions_vector_1.");
37 42915 : params.addParam<boundary_id_type>(
38 : "input_boundary_2_id",
39 28610 : 10000,
40 : "Boundary ID to be assigned to the boundary defined by positions_vector_2.");
41 42915 : params.addParam<boundary_id_type>("begin_side_boundary_id",
42 28610 : 10000,
43 : "Boundary ID to be assigned to the boundary connecting "
44 : "starting points of the positions_vectors.");
45 42915 : params.addParam<boundary_id_type>("end_side_boundary_id",
46 28610 : 10000,
47 : "Boundary ID to be assigned to the boundary connecting ending "
48 : "points of the positions_vectors.");
49 42915 : params.addParam<bool>(
50 : "use_quad_elements",
51 28610 : false,
52 : "Whether QUAD4 instead of TRI3 elements are used to construct the transition layer.");
53 42915 : params.addRangeCheckedParam<Real>(
54 : "bias_parameter",
55 28610 : 1.0,
56 : "bias_parameter>=0",
57 : "Parameter used to set up biasing of the layers: bias_parameter > 0.0 is used as the biasing "
58 : "factor; bias_parameter = 0.0 activates automatic biasing based on local node density on "
59 : "both input boundaries.");
60 42915 : params.addRangeCheckedParam<Real>(
61 : "gaussian_sigma",
62 28610 : 3.0,
63 : "gaussian_sigma>0.0",
64 : "Gaussian parameter used to smoothen local node density for automatic biasing; this "
65 : "parameter is not used if another biasing option is selected.");
66 14305 : params.addClassDescription("This FillBetweenCurvesGenerator object is designed to generate a "
67 : "transition layer to connect two boundaries of two input meshes.");
68 14305 : return params;
69 0 : }
70 :
71 20 : FillBetweenCurvesGenerator::FillBetweenCurvesGenerator(const InputParameters & parameters)
72 : : MeshGenerator(parameters),
73 20 : _input_name_1(getParam<MeshGeneratorName>("input_mesh_1")),
74 20 : _input_name_2(getParam<MeshGeneratorName>("input_mesh_2")),
75 20 : _mesh_1_shift(getParam<Point>("mesh_1_shift")),
76 20 : _mesh_2_shift(getParam<Point>("mesh_2_shift")),
77 20 : _num_layers(getParam<unsigned int>("num_layers")),
78 20 : _block_id(getParam<subdomain_id_type>("block_id")),
79 20 : _input_boundary_1_id(getParam<boundary_id_type>("input_boundary_1_id")),
80 20 : _input_boundary_2_id(getParam<boundary_id_type>("input_boundary_2_id")),
81 20 : _begin_side_boundary_id(getParam<boundary_id_type>("begin_side_boundary_id")),
82 20 : _end_side_boundary_id(getParam<boundary_id_type>("end_side_boundary_id")),
83 20 : _use_quad_elements(getParam<bool>("use_quad_elements")),
84 20 : _bias_parameter(getParam<Real>("bias_parameter")),
85 20 : _sigma(getParam<Real>("gaussian_sigma")),
86 20 : _input_1(getMeshByName(_input_name_1)),
87 40 : _input_2(getMeshByName(_input_name_2))
88 : {
89 20 : if (_input_name_1.compare(_input_name_2) == 0)
90 0 : paramError("input_mesh_2", "This parameter must be different from input_mesh_1.");
91 20 : }
92 :
93 : std::unique_ptr<MeshBase>
94 20 : FillBetweenCurvesGenerator::generate()
95 : {
96 20 : auto input_mesh_1 = dynamic_pointer_cast<ReplicatedMesh>(std::move(_input_1));
97 20 : auto input_mesh_2 = dynamic_pointer_cast<ReplicatedMesh>(std::move(_input_2));
98 20 : if (!input_mesh_1)
99 0 : paramError("input_mesh_1", "Input is not a replicated mesh, which is required.");
100 20 : if (!input_mesh_2)
101 0 : paramError("input_mesh_2", "Input is not a replicated mesh, which is required.");
102 :
103 20 : MeshTools::Modification::translate(
104 20 : *input_mesh_1, _mesh_1_shift(0), _mesh_1_shift(1), _mesh_1_shift(2));
105 20 : MeshTools::Modification::translate(
106 20 : *input_mesh_2, _mesh_2_shift(0), _mesh_2_shift(1), _mesh_2_shift(2));
107 :
108 : Real max_input_mesh_1_node_radius;
109 : Real max_input_mesh_2_node_radius;
110 20 : std::vector<dof_id_type> curve_1_ordered_nodes;
111 20 : std::vector<dof_id_type> curve_2_ordered_nodes;
112 :
113 : try
114 : {
115 20 : FillBetweenPointVectorsTools::isCurveOpenSingleSegment(*input_mesh_1,
116 : max_input_mesh_1_node_radius,
117 : curve_1_ordered_nodes,
118 20 : curveCentroidPoint(*input_mesh_1));
119 : }
120 0 : catch (MooseException & e)
121 : {
122 0 : paramError("input_mesh_1", e.what());
123 0 : }
124 :
125 : try
126 : {
127 20 : FillBetweenPointVectorsTools::isCurveOpenSingleSegment(*input_mesh_2,
128 : max_input_mesh_2_node_radius,
129 : curve_2_ordered_nodes,
130 20 : curveCentroidPoint(*input_mesh_2));
131 : }
132 0 : catch (MooseException & e)
133 : {
134 0 : paramError("input_mesh_2", e.what());
135 0 : }
136 :
137 20 : std::vector<Point> positions_vector_1;
138 20 : std::vector<Point> positions_vector_2;
139 :
140 180 : for (auto & curve_1_node_id : curve_1_ordered_nodes)
141 160 : positions_vector_1.push_back(*input_mesh_1->node_ptr(curve_1_node_id));
142 :
143 140 : for (auto & curve_2_node_id : curve_2_ordered_nodes)
144 120 : positions_vector_2.push_back(*input_mesh_2->node_ptr(curve_2_node_id));
145 :
146 20 : const boundary_id_type input_boundary_1_id = _input_boundary_1_id;
147 20 : const boundary_id_type input_boundary_2_id = _input_boundary_2_id;
148 20 : auto mesh = buildReplicatedMesh(2);
149 20 : FillBetweenPointVectorsTools::fillBetweenPointVectorsGenerator(*mesh,
150 : positions_vector_1,
151 : positions_vector_2,
152 20 : _num_layers,
153 20 : _block_id,
154 : input_boundary_1_id,
155 : input_boundary_2_id,
156 20 : _begin_side_boundary_id,
157 20 : _end_side_boundary_id,
158 20 : _type,
159 20 : _name,
160 20 : _use_quad_elements,
161 20 : _bias_parameter,
162 20 : _sigma);
163 :
164 : // Transfer over the nodesets
165 20 : BoundaryInfo & boundary = mesh->get_boundary_info();
166 20 : const BoundaryInfo & input_bdy_1 = input_mesh_1->get_boundary_info();
167 20 : const BoundaryInfo & input_bdy_2 = input_mesh_2->get_boundary_info();
168 :
169 : // Nodes could have been re-ordered during the FillBetweenPointVectors operation
170 : // We need to locate the nodes from input nodesets in the new mesh
171 20 : if (!mesh->is_prepared())
172 20 : mesh->prepare_for_use();
173 20 : auto pl = mesh->sub_point_locator();
174 :
175 20 : boundary_id_type offset = 0;
176 20 : const auto node_list_mesh1 = input_bdy_1.build_node_list();
177 60 : for (const auto & t : node_list_mesh1)
178 : {
179 : mooseAssert(pl->locate_node(*input_mesh_1->node_ptr(std::get<0>(t))),
180 : "We should have found the old node in input mesh 1");
181 40 : boundary.add_node(pl->locate_node(*input_mesh_1->node_ptr(std::get<0>(t))), std::get<1>(t));
182 40 : offset = std::max(std::get<1>(t), offset);
183 : }
184 :
185 20 : const auto node_list_mesh2 = input_bdy_2.build_node_list();
186 80 : for (const auto & t : node_list_mesh2)
187 : {
188 : mooseAssert(pl->locate_node(*input_mesh_1->node_ptr(std::get<0>(t))),
189 : "We should have found the old node in input mesh 2");
190 60 : boundary.add_node(pl->locate_node(*input_mesh_2->node_ptr(std::get<0>(t))),
191 60 : std::get<1>(t) + offset);
192 : }
193 :
194 30 : for (const auto & nodeset_pair : input_bdy_1.get_nodeset_name_map())
195 10 : boundary.set_nodeset_name_map().insert(nodeset_pair);
196 30 : for (const auto & [bnd_id, bnd_name] : input_bdy_2.get_nodeset_name_map())
197 10 : boundary.set_nodeset_name_map()[bnd_id + offset] = bnd_name;
198 20 : if (node_list_mesh1.size() + node_list_mesh2.size())
199 10 : mesh->set_isnt_prepared();
200 :
201 40 : return dynamic_pointer_cast<MeshBase>(mesh);
202 20 : }
203 :
204 : Point
205 40 : FillBetweenCurvesGenerator::curveCentroidPoint(const ReplicatedMesh & curve)
206 : {
207 40 : Point pt_tmp = Point(0.0, 0.0, 0.0);
208 40 : Real length_tmp = 0.0;
209 280 : for (const auto elem : curve.element_ptr_range())
210 : {
211 240 : Real elem_length = elem->hmax();
212 240 : pt_tmp += (elem->vertex_average()) * elem_length;
213 240 : length_tmp += elem_length;
214 40 : }
215 40 : return pt_tmp / length_tmp;
216 : }
|