20 "A collection of parameters defining an extrusion layer.");
25 "h", 1.0,
"Layer height. Cannot be specified if \"z\" is specified.");
29 "The z-coordinate at the top of the layer. "
30 "Cannot be specified if \"n\" is specified.");
44"Extrudes 2D geometry. Extrusion layers are"
45" specified using an \\ref chi_mesh__ExtrusionLayer specification which takes "
47" parameters: Pair A = \"n\" and \"z\", or Pair B = \"n\" and \"h\". When pair "
48"A is used then the z-levels will be computed automatically. Vice versa, when "
49"pair B is used then the h-levels will be computed automatically. Layers can be"
50" specified with a mixture of Pair A and Pair B. For example: Two main layers,"
51" one specified using a height, and the other specified using a z-level.");
60 "The name to associate with the top boundary.");
62 "bottom_boundary_name",
64 "The name to associate with the bottom boundary.");
71 top_boundary_name_(params.GetParamValue<std::string>(
"top_boundary_name")),
72 bottom_boundary_name_(
73 params.GetParamValue<std::string>(
"bottom_boundary_name"))
75 const auto& layers_param = params.
GetParam(
"layers");
77 double current_z_level = 0.0;
78 for (
const auto& layer_block : layers_param)
81 valid_params.SetErrorOriginScope(
"ExtruderMeshGenerator:\"layers\"");
82 valid_params.AssignParameters(layer_block);
84 const int h_and_z_config =
85 int(layer_block.Has(
"h")) + int(layer_block.Has(
"z"));
87 if (h_and_z_config != 1)
89 "be specified and also not both.");
91 auto n = valid_params.GetParamValue<uint32_t>(
"n");
93 if (layer_block.Has(
"h")) h = valid_params.GetParamValue<
double>(
"h");
96 double z = valid_params.GetParamValue<
double>(
"z");
98 "For extrusion layers, the \"z\" coordinates must "
99 "be monotonically increasing.");
100 h = z - current_z_level;
103 current_z_level += h;
108 <<
"Layer " << layer_block.Name() <<
" height=" << h
109 <<
" num_sub_layers=" << n <<
" top-z=" << current_z_level;
114std::unique_ptr<UnpartitionedMesh>
116 std::unique_ptr<UnpartitionedMesh> input_umesh)
122 not(input_umesh->GetMeshAttributes() &
DIMENSION_2),
123 "Input mesh is not 2D. A 2D mesh is required for extrusion");
125 const auto& template_vertices = input_umesh->GetVertices();
126 const auto& template_cells = input_umesh->GetRawCells();
128 const size_t num_template_vertices = template_vertices.size();
129 const size_t num_template_cells = template_cells.size();
135 for (
const auto& template_cell_ptr : template_cells)
137 const auto& template_cell = *template_cell_ptr;
139 throw std::logic_error(
"ExtruderMeshGenerator: "
140 "Template cell error. Not of base type POLYGON");
143 const auto& v0 = template_cell.centroid;
144 const auto& v1 = template_vertices[template_cell.vertex_ids[0]];
145 const auto& v2 = template_vertices[template_cell.vertex_ids[1]];
150 if (v01.Cross(v02).Dot(khat) < 0.0)
151 throw std::logic_error(
"Extruder attempting to extrude a template"
152 " cell with a normal pointing downward. This"
153 " causes erratic behavior and needs to be"
157 auto umesh = std::make_unique<UnpartitionedMesh>();
160 auto& umesh_bndry_map = umesh->GetMeshOptions().boundary_id_map;
161 umesh_bndry_map = input_umesh->GetMeshOptions().boundary_id_map;
169 double current_z = 0.0;
170 std::vector<double> z_levels = {current_z};
171 for (
const auto& layer :
layers_)
173 const double dz = layer.height_ / layer.num_sub_layers_;
174 for (uint32_t i = 0; i < layer.num_sub_layers_; ++i)
175 z_levels.push_back(current_z += dz);
180 auto& extruded_vertices = umesh->GetVertices();
181 for (
const double z_level : z_levels)
182 for (
const auto& template_vertex : template_vertices)
183 extruded_vertices.push_back(
184 Vec3(template_vertex.x, template_vertex.y, z_level));
188 for (
const auto& layer :
layers_)
190 for (uint32_t n = 0; n < layer.num_sub_layers_; ++n)
192 size_t tc_counter = 0;
193 for (
const auto& template_cell : template_cells)
198 switch (template_cell->sub_type)
209 auto& new_cell = *new_cell_ptr;
211 new_cell.material_id = template_cell->material_id;
214 const size_t tc_num_verts = template_cell->vertex_ids.size();
215 new_cell.vertex_ids.reserve(2 * tc_num_verts);
216 for (
const auto tc_vid : template_cell->vertex_ids)
217 new_cell.vertex_ids.push_back(tc_vid + k * num_template_vertices);
218 for (
const auto tc_vid : template_cell->vertex_ids)
219 new_cell.vertex_ids.push_back(tc_vid +
220 (k + 1) * num_template_vertices);
223 for (
const auto& tc_face : template_cell->faces)
229 new_face.
vertex_ids[0] = tc_face.vertex_ids[0] + k * num_template_vertices;
230 new_face.
vertex_ids[1] = tc_face.vertex_ids[1] + k * num_template_vertices;
231 new_face.
vertex_ids[2] = tc_face.vertex_ids[1] + (k + 1) * num_template_vertices;
232 new_face.
vertex_ids[3] = tc_face.vertex_ids[0] + (k + 1) * num_template_vertices;
235 if (tc_face.has_neighbor)
237 new_face.
neighbor = num_template_cells * k + tc_face.neighbor;
242 new_face.
neighbor = tc_face.neighbor;
246 new_cell.faces.push_back(std::move(new_face));
254 new_face.
vertex_ids.reserve(template_cell->vertex_ids.size());
255 for (
auto vid : template_cell->vertex_ids)
257 (k + 1) * num_template_vertices);
259 if (k == (z_levels.size()-2))
266 new_face.
neighbor = num_template_cells * (k+1) + tc_counter;
270 new_cell.faces.push_back(std::move(new_face));
277 new_face.
vertex_ids.reserve(template_cell->vertex_ids.size());
278 auto& vs = template_cell->vertex_ids;
279 for (
auto vid = vs.rbegin(); vid != vs.rend(); ++vid)
280 new_face.
vertex_ids.push_back((*vid) + k * num_template_vertices);
289 new_face.
neighbor = num_template_cells * (k-1) + tc_counter;
293 new_cell.faces.push_back(std::move(new_face));
295 umesh->GetRawCells().push_back(new_cell_ptr);
305 umesh->ComputeCentroidsAndCheckQuality();
306 umesh->BuildMeshConnectivity();
309 <<
"ExtruderMeshGenerator::GenerateUnpartitionedMesh Done";
#define ChiLogicalErrorIf(condition, message)
#define ChiInvalidArgumentIf(condition, message)
#define ChiInvalidArgument(message)
ParameterBlock & GetParam(const std::string ¶m_name)
std::unique_ptr< UnpartitionedMesh > GenerateUnpartitionedMesh(std::unique_ptr< UnpartitionedMesh > input_umesh) override
const std::string bottom_boundary_name_
static chi::InputParameters GetInputParameters()
ExtruderMeshGenerator(const chi::InputParameters ¶ms)
std::vector< ExtrusionLayer > layers_
const std::string top_boundary_name_
static chi::InputParameters GetInputParameters()
RegisterChiObject(chi_mesh, BooleanLogicalVolume)
RegisterChiObjectParametersOnly(chi_mesh, ExtrusionLayer)
static chi::InputParameters GetInputParameters()
std::vector< uint64_t > vertex_ids