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 14965 : SideSetsFromNormalsGenerator::validParams() 33 : { 34 14965 : InputParameters params = SideSetsGeneratorBase::validParams(); 35 : 36 29930 : params.addClassDescription( 37 : "Adds a new named sideset to the mesh for all faces matching the specified normal."); 38 44895 : params.addRequiredParam<std::vector<Point>>( 39 : "normals", "A list of normals for which to start painting sidesets"); 40 : 41 : // We want to use a different normal_tol for this generator than from the base class to preserve 42 : // old behavior. 43 44895 : params.setParameters("normal_tol", 1e-5); 44 : 45 : // We are using 'normals' instead 46 14965 : params.suppressParameter<Point>("normal"); 47 : 48 : // It doesn't make sense to allow internal sides for this side set generator. 49 44895 : params.setParameters("include_only_external_sides", true); 50 14965 : params.suppressParameter<bool>("include_only_external_sides"); 51 : 52 14965 : return params; 53 0 : } 54 : 55 49 : SideSetsFromNormalsGenerator::SideSetsFromNormalsGenerator(const InputParameters & parameters) 56 : : SideSetsGeneratorBase(parameters), 57 49 : _normals(getParam<std::vector<Point>>("normals")), 58 49 : _boundary_to_normal_map( 59 147 : declareMeshProperty<std::map<BoundaryID, RealVectorValue>>("boundary_normals")) 60 : { 61 : // Get the BoundaryIDs from the mesh 62 49 : if (_normals.size() != _boundary_names.size()) 63 0 : mooseError("normal list and boundary list are not the same length"); 64 : 65 : // Make sure that the normals are normalized 66 156 : for (auto & normal : _normals) 67 : { 68 107 : if (normal.norm() < 1e-5) 69 0 : mooseError("Normal is zero"); 70 107 : normal /= normal.norm(); 71 : } 72 : 73 49 : _using_normal = true; 74 49 : } 75 : 76 : std::unique_ptr<MeshBase> 77 48 : SideSetsFromNormalsGenerator::generate() 78 : { 79 48 : std::unique_ptr<MeshBase> mesh = std::move(_input); 80 48 : if (!_fixed_normal && !mesh->is_replicated()) 81 0 : mooseError("SideSetsFromNormalsGenerator is not implemented for distributed meshes when " 82 : "fixed_normal = false"); 83 : 84 : std::vector<BoundaryID> boundary_ids = 85 48 : MooseMeshUtils::getBoundaryIDs(*mesh, _boundary_names, true); 86 : 87 48 : setup(*mesh); 88 : 89 48 : _visited.clear(); 90 : 91 : // Request to compute normal vectors 92 48 : const std::vector<Point> & face_normals = _fe_face->get_normals(); 93 : 94 : // We'll need to loop over all of the elements to find ones that match this normal. 95 : // We can't rely on flood catching them all here... 96 78840 : for (const auto & elem : mesh->element_ptr_range()) 97 254116 : for (const auto side : make_range(elem->n_sides())) 98 : { 99 214720 : if (elem->neighbor_ptr(side)) 100 196104 : continue; 101 : 102 18616 : _fe_face->reinit(elem, side); 103 : 104 : // We'll just use the normal of the first qp 105 18616 : const Point & face_normal = face_normals[0]; 106 : 107 63318 : for (const auto i : make_range(boundary_ids.size())) 108 : { 109 44702 : if (normalsWithinTol(_normals[i], face_normal, _normal_tol)) 110 6607 : flood(elem, _normals[i], boundary_ids[i], *mesh); 111 : } 112 48 : } 113 : 114 48 : finalize(); 115 : 116 48 : BoundaryInfo & boundary_info = mesh->get_boundary_info(); 117 153 : for (const auto i : make_range(boundary_ids.size())) 118 : { 119 105 : boundary_info.sideset_name(boundary_ids[i]) = _boundary_names[i]; 120 105 : _boundary_to_normal_map[boundary_ids[i]] = _normals[i]; 121 : } 122 : 123 : // This is a terrible hack that we'll want to remove once BMBBG isn't terrible 124 48 : if (!_app.getMeshGeneratorSystem().hasBreakMeshByBlockGenerator()) 125 48 : mesh->set_isnt_prepared(); 126 96 : return dynamic_pointer_cast<MeshBase>(mesh); 127 48 : }