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 "SideSetsFromNormalsGenerator.h" 11 : #include "Parser.h" 12 : #include "InputParameters.h" 13 : #include "MooseMeshUtils.h" 14 : #include "CastUniquePointer.h" 15 : #include "MooseApp.h" 16 : #include "MeshGeneratorSystem.h" 17 : 18 : #include "libmesh/mesh_generation.h" 19 : #include "libmesh/mesh.h" 20 : #include "libmesh/string_to_enum.h" 21 : #include "libmesh/quadrature_gauss.h" 22 : #include "libmesh/point_locator_base.h" 23 : #include "libmesh/distributed_mesh.h" 24 : #include "libmesh/elem.h" 25 : #include "libmesh/fe_base.h" 26 : 27 : #include <typeinfo> 28 : 29 : registerMooseObject("MooseApp", SideSetsFromNormalsGenerator); 30 : 31 : InputParameters 32 14357 : SideSetsFromNormalsGenerator::validParams() 33 : { 34 14357 : InputParameters params = SideSetsGeneratorBase::validParams(); 35 : 36 14357 : params.addClassDescription( 37 : "Adds a new named sideset to the mesh for all faces matching the specified normal."); 38 14357 : params.addRequiredParam<std::vector<Point>>( 39 : "normals", "A list of normals for which to start painting sidesets"); 40 14357 : params.addParam<Real>("tolerance", "Tolerance for comparing the face normal"); 41 14357 : params.deprecateParam("tolerance", "normal_tol", "4/01/2025"); 42 : 43 : // We want to use a different normal_tol for this generator than from the base class to preserve 44 : // old behavior. 45 14357 : params.setParameters("normal_tol", 1e-5); 46 : 47 : // We are using 'normals' instead 48 14357 : params.suppressParameter<Point>("normal"); 49 : 50 : // It doesn't make sense to allow internal sides for this side set generator. 51 14357 : params.setParameters("include_only_external_sides", true); 52 14357 : params.suppressParameter<bool>("include_only_external_sides"); 53 : 54 14357 : return params; 55 0 : } 56 : 57 46 : SideSetsFromNormalsGenerator::SideSetsFromNormalsGenerator(const InputParameters & parameters) 58 : : SideSetsGeneratorBase(parameters), 59 46 : _normals(getParam<std::vector<Point>>("normals")), 60 46 : _boundary_to_normal_map( 61 92 : declareMeshProperty<std::map<BoundaryID, RealVectorValue>>("boundary_normals")) 62 : { 63 : // Get the BoundaryIDs from the mesh 64 46 : if (_normals.size() != _boundary_names.size()) 65 0 : mooseError("normal list and boundary list are not the same length"); 66 : 67 : // Make sure that the normals are normalized 68 146 : for (auto & normal : _normals) 69 : { 70 100 : if (normal.norm() < 1e-5) 71 0 : mooseError("Normal is zero"); 72 100 : normal /= normal.norm(); 73 : } 74 : 75 46 : _using_normal = true; 76 46 : } 77 : 78 : std::unique_ptr<MeshBase> 79 45 : SideSetsFromNormalsGenerator::generate() 80 : { 81 45 : std::unique_ptr<MeshBase> mesh = std::move(_input); 82 45 : if (!_fixed_normal && !mesh->is_replicated()) 83 0 : mooseError("SideSetsFromNormalsGenerator is not implemented for distributed meshes when " 84 : "fixed_normal = false"); 85 : 86 : std::vector<BoundaryID> boundary_ids = 87 45 : MooseMeshUtils::getBoundaryIDs(*mesh, _boundary_names, true); 88 : 89 45 : setup(*mesh); 90 : 91 45 : _visited.clear(); 92 : 93 : // Request to compute normal vectors 94 45 : const std::vector<Point> & face_normals = _fe_face->get_normals(); 95 : 96 : // We'll need to loop over all of the elements to find ones that match this normal. 97 : // We can't rely on flood catching them all here... 98 71965 : for (const auto & elem : mesh->element_ptr_range()) 99 230072 : for (const auto side : make_range(elem->n_sides())) 100 : { 101 194112 : if (elem->neighbor_ptr(side)) 102 177164 : continue; 103 : 104 16948 : _fe_face->reinit(elem, side); 105 : 106 : // We'll just use the normal of the first qp 107 16948 : const Point & face_normal = face_normals[0]; 108 : 109 57484 : for (const auto i : make_range(boundary_ids.size())) 110 : { 111 40536 : if (normalsWithinTol(_normals[i], face_normal, _normal_tol)) 112 6002 : flood(elem, _normals[i], boundary_ids[i], *mesh); 113 : } 114 45 : } 115 : 116 45 : finalize(); 117 : 118 45 : BoundaryInfo & boundary_info = mesh->get_boundary_info(); 119 143 : for (const auto i : make_range(boundary_ids.size())) 120 : { 121 98 : boundary_info.sideset_name(boundary_ids[i]) = _boundary_names[i]; 122 98 : _boundary_to_normal_map[boundary_ids[i]] = _normals[i]; 123 : } 124 : 125 : // This is a terrible hack that we'll want to remove once BMBBG isn't terrible 126 45 : if (!_app.getMeshGeneratorSystem().hasBreakMeshByBlockGenerator()) 127 45 : mesh->set_isnt_prepared(); 128 90 : return dynamic_pointer_cast<MeshBase>(mesh); 129 45 : }