|
| 1 | +//* This file is part of the MOOSE framework |
| 2 | +//* https://www.mooseframework.org |
| 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 "SidesetsEncloseBlocks.h" |
| 11 | +#include "InputParameters.h" |
| 12 | +#include "MooseTypes.h" |
| 13 | +#include "MooseMeshUtils.h" |
| 14 | +#include "CastUniquePointer.h" |
| 15 | + |
| 16 | +#include "libmesh/remote_elem.h" |
| 17 | + |
| 18 | +registerMooseObject("MooseApp", SidesetsEncloseBlocks); |
| 19 | + |
| 20 | +defineLegacyParams(SidesetsEncloseBlocks); |
| 21 | + |
| 22 | +InputParameters |
| 23 | +SidesetsEncloseBlocks::validParams() |
| 24 | +{ |
| 25 | + InputParameters params = MeshGenerator::validParams(); |
| 26 | + |
| 27 | + params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify"); |
| 28 | + params.addParam<std::vector<SubdomainName>>( |
| 29 | + "block", "The set of blocks that are checked if they are enclosed by boundary"); |
| 30 | + params.addParam<std::vector<BoundaryName>>("boundary", |
| 31 | + "The name of the boundaries enclosing the "); |
| 32 | + params.addParam<BoundaryName>("new_boundary", "The name of the boundary to create"); |
| 33 | + params.addClassDescription( |
| 34 | + "MeshGenerator that checks if a set of blocks is enclosed by a set of sidesets." |
| 35 | + "It can either add sides that are not covered by a sideset by a new sidesets or" |
| 36 | + "error out."); |
| 37 | + |
| 38 | + return params; |
| 39 | +} |
| 40 | + |
| 41 | +SidesetsEncloseBlocks::SidesetsEncloseBlocks(const InputParameters & parameters) |
| 42 | + : MeshGenerator(parameters), _input(getMesh("input")) |
| 43 | +{ |
| 44 | +} |
| 45 | + |
| 46 | +std::unique_ptr<MeshBase> |
| 47 | +SidesetsEncloseBlocks::generate() |
| 48 | +{ |
| 49 | + std::unique_ptr<MeshBase> mesh = std::move(_input); |
| 50 | + |
| 51 | + // Get a reference to our BoundaryInfo object for later use |
| 52 | + BoundaryInfo & boundary_info = mesh->get_boundary_info(); |
| 53 | + |
| 54 | + // get a list of all sides; vector of tuples (elem, loc_side, side_set) |
| 55 | + auto side_list = boundary_info.build_active_side_list(); |
| 56 | + |
| 57 | + // error on finding a side that is not covered |
| 58 | + bool error_out = !isParamValid("new_boundary"); |
| 59 | + boundary_id_type new_sideset_id; |
| 60 | + if (!error_out) |
| 61 | + { |
| 62 | + BoundaryName new_boundary = getParam<BoundaryName>("new_boundary"); |
| 63 | + std::stringstream ss; |
| 64 | + ss << new_boundary; |
| 65 | + ss >> new_sideset_id; |
| 66 | + if (ss.fail()) |
| 67 | + new_sideset_id = boundary_info.get_id_by_name(new_boundary); |
| 68 | + |
| 69 | + // make sure that _sideset exists |
| 70 | + if (new_sideset_id == BoundaryInfo::invalid_id) |
| 71 | + paramError("new_boundary", "Not a valid boundary"); |
| 72 | + } |
| 73 | + |
| 74 | + // get blocks |
| 75 | + std::vector<subdomain_id_type> vec_block_ids = |
| 76 | + MooseMeshUtils::getSubdomainIDs(*mesh, getParam<std::vector<SubdomainName>>("block")); |
| 77 | + std::set<subdomain_id_type> blk_ids(vec_block_ids.begin(), vec_block_ids.end()); |
| 78 | + |
| 79 | + // get boundaries |
| 80 | + // check if the provided sideset name is actually a sideset id |
| 81 | + // if _sideset_name can be converted to integer it's interpreted |
| 82 | + // as sideset id |
| 83 | + auto boundary_name_vec = getParam<std::vector<BoundaryName>>("boundary"); |
| 84 | + std::vector<boundary_id_type> bnd_ids_vec; |
| 85 | + bnd_ids_vec.reserve(boundary_name_vec.size()); |
| 86 | + std::set<boundary_id_type> bnd_ids; |
| 87 | + for (auto & bnd_name : boundary_name_vec) |
| 88 | + { |
| 89 | + std::stringstream ss; |
| 90 | + boundary_id_type sideset_id; |
| 91 | + ss << bnd_name; |
| 92 | + ss >> sideset_id; |
| 93 | + if (ss.fail()) |
| 94 | + sideset_id = boundary_info.get_id_by_name(bnd_name); |
| 95 | + |
| 96 | + // make sure that _sideset exists |
| 97 | + if (sideset_id == BoundaryInfo::invalid_id) |
| 98 | + paramError("boundary", "Not a valid boundary"); |
| 99 | + bnd_ids_vec.push_back(sideset_id); |
| 100 | + bnd_ids.insert(sideset_id); |
| 101 | + } |
| 102 | + |
| 103 | + // loop over all elements in blocks and for each elem over each side |
| 104 | + // and check the neighbors |
| 105 | + for (auto & block_id : blk_ids) |
| 106 | + { |
| 107 | + for (const Elem * elem : as_range(mesh->active_local_subdomain_elements_begin(block_id), |
| 108 | + mesh->active_local_subdomain_elements_end(block_id))) |
| 109 | + { |
| 110 | + // loop through sides |
| 111 | + for (unsigned int j = 0; j < elem->n_sides(); ++j) |
| 112 | + { |
| 113 | + const Elem * neigh = elem->neighbor_ptr(j); |
| 114 | + |
| 115 | + // is this an outside boundary to blocks? |
| 116 | + // NOTE: the next line is NOT sufficient for AMR!! |
| 117 | + bool is_outer_bnd = !neigh || blk_ids.find(neigh->subdomain_id()) == blk_ids.end(); |
| 118 | + if (is_outer_bnd) |
| 119 | + { |
| 120 | + // get all boundary ids of this side, then compare the set of these boundary_ids |
| 121 | + // to the set of boundary_ids provided to the mesh generator; if the intersection |
| 122 | + // is empty then this side is NOT convered |
| 123 | + std::vector<boundary_id_type> side_boundary_ids_vec; |
| 124 | + boundary_info.raw_boundary_ids(elem, j, side_boundary_ids_vec); |
| 125 | + |
| 126 | + std::set<boundary_id_type> intersection; |
| 127 | + std::set_intersection(side_boundary_ids_vec.begin(), |
| 128 | + side_boundary_ids_vec.end(), |
| 129 | + bnd_ids_vec.begin(), |
| 130 | + bnd_ids_vec.end(), |
| 131 | + std::inserter(intersection, intersection.end())); |
| 132 | + // is intersection emtpy? |
| 133 | + if (intersection.size() == 0) |
| 134 | + { |
| 135 | + if (error_out) |
| 136 | + mooseError("Element id ", |
| 137 | + elem->id(), |
| 138 | + " side ", |
| 139 | + j, |
| 140 | + " is external and not covered by specified boundaries."); |
| 141 | + else |
| 142 | + boundary_info.add_side(elem, j, new_sideset_id); |
| 143 | + } |
| 144 | + } |
| 145 | + } |
| 146 | + } |
| 147 | + } |
| 148 | + |
| 149 | + return dynamic_pointer_cast<MeshBase>(mesh); |
| 150 | +} |
0 commit comments