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 "DeleteElementsNearMeshGenerator.h" 11 : #include "SetupQuadratureAction.h" 12 : #include "KDTree.h" 13 : 14 : #include "libmesh/type_vector.h" 15 : #include "libmesh/point.h" 16 : #include "libmesh/elem.h" 17 : #include "libmesh/fe_base.h" 18 : #include "libmesh/quadrature_gauss.h" 19 : 20 : registerMooseObject("MooseApp", DeleteElementsNearMeshGenerator); 21 : 22 : InputParameters 23 3077 : DeleteElementsNearMeshGenerator::validParams() 24 : { 25 3077 : InputParameters params = ElementDeletionGeneratorBase::validParams(); 26 : 27 6154 : params.addClassDescription( 28 : "Removes elements lying \"near\" another mesh. The proximity is examined by the distance " 29 : "from " 30 : "the element's centroid to the faces of elements of the \"proximity_mesh\""); 31 12308 : params.addRequiredParam<MeshGeneratorName>("proximity_mesh", 32 : "Mesh providing the deletion criterion"); 33 15385 : params.addRequiredRangeCheckedParam<Real>( 34 : "distance", 35 : "distance>0", 36 : "The distance from the centroid of elements in the 'input' mesh to elements in the " 37 : "'proximity_mesh' under which they are marked for deletion"); 38 3077 : auto options_order = SetupQuadratureAction::getQuadratureOrderEnum(); 39 3077 : options_order.assign(CONSTANT); 40 9231 : params.addParam<MooseEnum>("side_order", 41 : options_order, 42 : "Order of the face quadrature used to find the nearest face in the " 43 : "'proximity_mesh'. Default is CONSTANT"); 44 : 45 6154 : return params; 46 3077 : } 47 : 48 8 : DeleteElementsNearMeshGenerator::DeleteElementsNearMeshGenerator(const InputParameters & parameters) 49 : : ElementDeletionGeneratorBase(parameters), 50 8 : _proximity_mesh(getMesh("proximity_mesh")), 51 24 : _distance(getParam<Real>("distance")) 52 : { 53 8 : } 54 : 55 : std::unique_ptr<MeshBase> 56 8 : DeleteElementsNearMeshGenerator::generate() 57 : { 58 : // Build the point locator to detect elements inside 59 8 : _pl = _proximity_mesh->sub_point_locator(); 60 8 : _pl->enable_out_of_mesh_mode(); 61 : 62 : // Build a KNN with side Qps. This will help locate the nearest side if known to be outside 63 : // NOTE: side Qps are just one option. We could have done nodes, side centroids (~ side Qp at 64 : // order 0) 65 8 : std::vector<Point> all_side_qps; 66 16 : const auto & order = getParam<MooseEnum>("side_order"); 67 8 : const auto order_enum = Moose::stringToEnum<Order>(order); 68 24 : for (const auto * const elem : _proximity_mesh->element_ptr_range()) 69 : { 70 : // Build side then side Qps 71 16 : const auto dim = elem->dim(); 72 80 : for (const auto side_i : make_range(elem->n_sides())) 73 : { 74 : // Internal sides cannot be closest to an external point 75 64 : if (elem->neighbor_ptr(side_i)) 76 16 : continue; 77 48 : const std::unique_ptr<const Elem> face = elem->build_side_ptr(side_i); 78 : std::unique_ptr<libMesh::FEBase> fe( 79 48 : libMesh::FEBase::build(dim, libMesh::FEType(elem->default_order()))); 80 48 : libMesh::QGauss qface(dim - 1, order_enum); 81 48 : fe->attach_quadrature_rule(&qface); 82 48 : const auto & qpoints = fe->get_xyz(); 83 48 : fe->reinit(elem, side_i); 84 48 : all_side_qps.insert(all_side_qps.end(), qpoints.begin(), qpoints.end()); 85 48 : } 86 8 : } 87 : mooseAssert(!all_side_qps.empty(), "Should have found side Qps"); 88 8 : _kd_tree = std::make_unique<KDTree>(all_side_qps, /*max leaf size*/ 1); 89 : 90 : // Abide by the rules 91 : // NOTE: don't use _proximity_mesh in shouldDelete()! It won't work, it's gone 92 8 : const auto prox_mg = std::move(_proximity_mesh); 93 : 94 : // Perform the deletions 95 16 : return ElementDeletionGeneratorBase::generate(); 96 8 : } 97 : 98 : bool 99 288 : DeleteElementsNearMeshGenerator::shouldDelete(const Elem * elem) 100 : { 101 1224 : const auto delete_due_to_point = [this](const Point & pt) -> bool 102 : { 103 : // Proximity mesh contains the point, distance is zero 104 1224 : if ((*_pl)(pt)) 105 104 : return true; 106 : 107 : // Use the KNN to get the distance 108 2240 : std::vector<Real> distance_sqr(2); 109 1120 : std::vector<std::size_t> return_indices(2); 110 1120 : _kd_tree->neighborSearch(pt, /*num_search*/ 1, return_indices, distance_sqr); 111 : const auto distance = 112 1120 : distance_sqr.empty() ? std::numeric_limits<Real>::max() : std::sqrt(distance_sqr[0]); 113 : 114 1120 : return distance < _distance; 115 1120 : }; 116 : 117 : // Check element centroid 118 288 : const auto centroid = elem->vertex_average(); 119 288 : if (delete_due_to_point(centroid)) 120 32 : return true; 121 : 122 : // Then its nodes. For convex elements, this should be enough 123 1120 : for (const auto & node : elem->node_ref_range()) 124 936 : if (delete_due_to_point(node)) 125 72 : return true; 126 : 127 184 : return false; 128 : }