LCOV - code coverage report
Current view: top level - src/meshgenerators - PolygonMeshTrimmerBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose reactor: #32971 (54bef8) with base c6cf66 Lines: 101 120 84.2 %
Date: 2026-05-29 20:39:24 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          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 "PolygonMeshTrimmerBase.h"
      11             : #include "MooseMeshXYCuttingUtils.h"
      12             : #include "MooseMeshUtils.h"
      13             : #include "MathUtils.h"
      14             : 
      15             : // C++ includes
      16             : #include <cmath> // provides round, not std::round (see http://www.cplusplus.com/reference/cmath/round/)
      17             : 
      18             : InputParameters
      19         540 : PolygonMeshTrimmerBase::validParams()
      20             : {
      21         540 :   InputParameters params = PolygonMeshGeneratorBase::validParams();
      22        1080 :   params.addRequiredParam<MeshGeneratorName>("input", "The input mesh that needs to be trimmed.");
      23        1080 :   params.addParam<BoundaryName>("peripheral_trimming_section_boundary",
      24             :                                 "Boundary formed by peripheral trimming.");
      25        1080 :   params.addRangeCheckedParam<short>(
      26             :       "center_trim_starting_index",
      27             :       "center_trim_starting_index>=0 & center_trim_starting_index<12",
      28             :       "Index of the starting center trimming position.");
      29        1080 :   params.addRangeCheckedParam<short>("center_trim_ending_index",
      30             :                                      "center_trim_ending_index>=0 & center_trim_ending_index<12",
      31             :                                      "Index of the ending center trimming position.");
      32        1080 :   params.addParam<BoundaryName>("center_trimming_section_boundary",
      33             :                                 "Boundary formed by center trimming (external_boundary will be "
      34             :                                 "assigned if this parameter is not provided).");
      35        1080 :   params.addParam<BoundaryName>("external_boundary",
      36             :                                 "External boundary of the input mesh prior to the trimming.");
      37        1080 :   params.addParam<SubdomainName>(
      38             :       "tri_elem_subdomain_name_suffix",
      39             :       "trimmer_tri",
      40             :       "Suffix to the block name used for quad elements that are trimmed/converted into "
      41             :       "triangular elements to avert degenerate quad elements");
      42        1080 :   params.addParam<subdomain_id_type>(
      43             :       "tri_elem_subdomain_shift",
      44             :       "Customized id shift to define subdomain ids of the converted triangular elements.");
      45             : 
      46        1080 :   params.addParamNamesToGroup(
      47             :       "center_trim_starting_index center_trim_ending_index center_trimming_section_boundary",
      48             :       "Center Trimming");
      49        1080 :   params.addParamNamesToGroup("peripheral_trimming_section_boundary", "Peripheral Trimming");
      50        1080 :   params.addParamNamesToGroup("tri_elem_subdomain_name_suffix tri_elem_subdomain_shift",
      51             :                               "Trimmed Boundary Repair");
      52             : 
      53         540 :   params.addClassDescription("This PolygonMeshTrimmerBase is the base class for "
      54             :                              "CartesianMeshTrimmer and HexagonMeshTrimmer.");
      55             : 
      56         540 :   return params;
      57           0 : }
      58             : 
      59         278 : PolygonMeshTrimmerBase::PolygonMeshTrimmerBase(const InputParameters & parameters)
      60             :   : PolygonMeshGeneratorBase(parameters),
      61           0 :     _input_name(getParam<MeshGeneratorName>("input")),
      62         556 :     _trim_peripheral_region(getParam<std::vector<unsigned short>>("trim_peripheral_region")),
      63         440 :     _peripheral_trimming_section_boundary(
      64         278 :         isParamValid("peripheral_trimming_section_boundary")
      65         278 :             ? getParam<BoundaryName>("peripheral_trimming_section_boundary")
      66             :             : BoundaryName()),
      67         382 :     _center_trimming_section_boundary(
      68         278 :         isParamValid("center_trimming_section_boundary")
      69         278 :             ? getParam<BoundaryName>("center_trimming_section_boundary")
      70             :             : BoundaryName()),
      71         560 :     _external_boundary_name(isParamValid("external_boundary")
      72         278 :                                 ? getParam<BoundaryName>("external_boundary")
      73             :                                 : BoundaryName()),
      74         278 :     _tri_elem_subdomain_name_suffix(getParam<SubdomainName>("tri_elem_subdomain_name_suffix")),
      75         278 :     _tri_elem_subdomain_shift(isParamValid("tri_elem_subdomain_shift")
      76         278 :                                   ? getParam<subdomain_id_type>("tri_elem_subdomain_shift")
      77             :                                   : Moose::INVALID_BLOCK_ID),
      78         556 :     _input(getMeshByName(_input_name))
      79             : {
      80         278 :   declareMeshProperty("pattern_pitch_meta", 0.0);
      81         278 :   declareMeshProperty("input_pitch_meta", 0.0);
      82         556 :   declareMeshProperty("is_control_drum_meta", false);
      83         278 :   if (std::accumulate(_trim_peripheral_region.begin(), _trim_peripheral_region.end(), 0) == 0 &&
      84             :       !_peripheral_trimming_section_boundary.empty())
      85           4 :     paramError("peripheral_trimming_section_boundary",
      86             :                "this input parameter is not used if peripheral trimming is not performed.");
      87         274 : }
      88             : 
      89             : std::unique_ptr<MeshBase>
      90         250 : PolygonMeshTrimmerBase::generate()
      91             : {
      92         250 :   auto replicated_mesh_ptr = dynamic_cast<ReplicatedMesh *>(_input.get());
      93         250 :   if (!replicated_mesh_ptr)
      94           0 :     paramError("input", "Input is not a replicated mesh, which is required");
      95             : 
      96             :   ReplicatedMesh & mesh = *replicated_mesh_ptr;
      97             : 
      98             :   // Passing metadata
      99         500 :   if (hasMeshProperty<Real>("input_pitch_meta", _input_name))
     100         444 :     setMeshProperty("input_pitch_meta", getMeshProperty<Real>("input_pitch_meta", _input_name));
     101         500 :   if (hasMeshProperty<bool>("is_control_drum_meta", _input_name))
     102         472 :     setMeshProperty("is_control_drum_meta",
     103             :                     getMeshProperty<bool>("is_control_drum_meta", _input_name));
     104             : 
     105             :   const boundary_id_type external_boundary_id =
     106             :       _external_boundary_name.empty()
     107         250 :           ? (boundary_id_type)OUTER_SIDESET_ID
     108           4 :           : MooseMeshUtils::getBoundaryID(_external_boundary_name, mesh);
     109         250 :   if (external_boundary_id == libMesh::BoundaryInfo::invalid_id)
     110           4 :     paramError("external_boundary",
     111             :                "the provided external boundary does not exist in the input mesh.");
     112             : 
     113         246 :   if (!mesh.preparation().has_cached_elem_data)
     114         232 :     mesh.cache_elem_data();
     115             :   std::set<subdomain_id_type> subdomain_ids_set;
     116         246 :   mesh.subdomain_ids(subdomain_ids_set);
     117             : 
     118         246 :   if (*max_element(_trim_peripheral_region.begin(), _trim_peripheral_region.end()))
     119             :   {
     120             :     const boundary_id_type peripheral_trimming_section_boundary_id =
     121             :         _peripheral_trimming_section_boundary.empty()
     122         310 :             ? external_boundary_id
     123         464 :             : (MooseMeshUtils::getBoundaryIDs(mesh, {_peripheral_trimming_section_boundary}, true))
     124             :                   .front();
     125         156 :     peripheralTrimmer(mesh,
     126         156 :                       _trim_peripheral_region,
     127             :                       external_boundary_id,
     128             :                       peripheral_trimming_section_boundary_id,
     129             :                       subdomain_ids_set);
     130         156 :     mesh.get_boundary_info().sideset_name(peripheral_trimming_section_boundary_id) =
     131         156 :         _peripheral_trimming_section_boundary;
     132             :   }
     133         180 :   else if (hasMeshProperty<Real>("pattern_pitch_meta", _input_name))
     134         152 :     setMeshProperty("pattern_pitch_meta", getMeshProperty<Real>("pattern_pitch_meta", _input_name));
     135             : 
     136         246 :   if (_center_trim_sector_number < _num_sides * 2)
     137             :   {
     138             :     const boundary_id_type center_trimming_section_boundary_id =
     139             :         _center_trimming_section_boundary.empty()
     140         204 :             ? external_boundary_id
     141         304 :             : (MooseMeshUtils::getBoundaryIDs(mesh, {_center_trimming_section_boundary}, true))
     142             :                   .front();
     143         212 :     centerTrimmer(mesh,
     144             :                   _num_sides,
     145         104 :                   _center_trim_sector_number,
     146         104 :                   _trimming_start_sector,
     147             :                   external_boundary_id,
     148             :                   center_trimming_section_boundary_id,
     149             :                   subdomain_ids_set);
     150         104 :     mesh.get_boundary_info().sideset_name(center_trimming_section_boundary_id) =
     151         104 :         _center_trimming_section_boundary;
     152             :   }
     153             : 
     154         242 :   if (MooseMeshXYCuttingUtils::quasiTriElementsFixer(
     155         246 :           mesh, subdomain_ids_set, _tri_elem_subdomain_shift, _tri_elem_subdomain_name_suffix))
     156          63 :     mesh.prepare_for_use();
     157             : 
     158         238 :   return std::move(_input);
     159             : }
     160             : 
     161             : void
     162         104 : PolygonMeshTrimmerBase::centerTrimmer(ReplicatedMesh & mesh,
     163             :                                       const unsigned int num_sides,
     164             :                                       const unsigned int center_trim_sector_number,
     165             :                                       const unsigned int trimming_start_sector,
     166             :                                       const boundary_id_type external_boundary_id,
     167             :                                       const boundary_id_type center_trimming_section_boundary_id,
     168             :                                       const std::set<subdomain_id_type> subdomain_ids_set)
     169             : {
     170         104 :   const subdomain_id_type max_subdomain_id = *subdomain_ids_set.rbegin();
     171         104 :   const subdomain_id_type block_id_to_remove = max_subdomain_id + 1;
     172             : 
     173             :   std::vector<std::vector<Real>> bdry_pars = {
     174         104 :       {std::cos((Real)trimming_start_sector * M_PI / (Real)num_sides),
     175         104 :        std::sin((Real)trimming_start_sector * M_PI / (Real)num_sides),
     176             :        0.0},
     177         104 :       {-std::cos((Real)(trimming_start_sector + center_trim_sector_number) * M_PI /
     178             :                  (Real)num_sides),
     179         104 :        -std::sin((Real)(trimming_start_sector + center_trim_sector_number) * M_PI /
     180             :                  (Real)num_sides),
     181         312 :        0.0}};
     182             : 
     183         312 :   for (unsigned int i = 0; i < bdry_pars.size(); i++)
     184             :     try
     185             :     {
     186         208 :       MooseMeshXYCuttingUtils::lineRemoverMoveNode(mesh,
     187             :                                                    bdry_pars[i],
     188             :                                                    block_id_to_remove,
     189             :                                                    subdomain_ids_set,
     190             :                                                    center_trimming_section_boundary_id,
     191             :                                                    external_boundary_id);
     192             :     }
     193           0 :     catch (MooseException & e)
     194             :     {
     195           0 :       if (((std::string)e.what())
     196           0 :               .compare("The input mesh has degenerate quad element before trimming.") == 0)
     197           0 :         paramError("input", "The input mesh has degenerate quad element before trimming.");
     198           0 :       else if (((std::string)e.what())
     199           0 :                    .compare("The new subdomain name already exists in the mesh.") == 0)
     200           0 :         paramError("tri_elem_subdomain_name_suffix",
     201             :                    "The new subdomain name already exists in the mesh.");
     202           0 :     }
     203         312 : }
     204             : 
     205             : void
     206         156 : PolygonMeshTrimmerBase::peripheralTrimmer(
     207             :     ReplicatedMesh & mesh,
     208             :     const std::vector<unsigned short> trim_peripheral_region,
     209             :     const boundary_id_type external_boundary_id,
     210             :     const boundary_id_type peripheral_trimming_section_boundary_id,
     211             :     const std::set<subdomain_id_type> subdomain_ids_set)
     212             : {
     213         156 :   const unsigned int num_sides = trim_peripheral_region.size();
     214         156 :   const subdomain_id_type max_subdomain_id = *subdomain_ids_set.rbegin();
     215         156 :   const subdomain_id_type block_id_to_remove = max_subdomain_id + 1;
     216             : 
     217         156 :   const Real unit_length = getMeshProperty<Real>("input_pitch_meta", _input_name) /
     218         240 :                            (num_sides == 6 ? std::sqrt(3.0) : 2.0);
     219             :   // Add metadata to input
     220         156 :   const Real multiplier = ((Real)getMeshProperty<unsigned int>("pattern_size", _input_name) - 1.0) *
     221         240 :                           (num_sides == 6 ? 0.75 : 1.0);
     222         156 :   const Real ch_length = multiplier * unit_length;
     223         312 :   setMeshProperty("pattern_pitch_meta", ch_length * 2.0);
     224             : 
     225             :   std::vector<std::vector<Real>> bdry_pars;
     226         156 :   if (num_sides == 6)
     227         504 :     bdry_pars = {{1.0 / std::sqrt(3.0), 1.0, -ch_length / std::sqrt(3.0) * 2.0},
     228             :                  {-1.0 / std::sqrt(3.0), 1.0, -ch_length / std::sqrt(3.0) * 2.0},
     229             :                  {-1.0, 0.0, -ch_length},
     230             :                  {-1.0 / std::sqrt(3.0), -1.0, -ch_length / std::sqrt(3.0) * 2.0},
     231             :                  {1.0 / std::sqrt(3.0), -1.0, -ch_length / std::sqrt(3.0) * 2.0},
     232         504 :                  {1.0, 0.0, -ch_length}};
     233             :   else
     234         420 :     bdry_pars = {{1.0, 0.0, -ch_length},
     235             :                  {0.0, 1.0, -ch_length},
     236             :                  {-1.0, 0.0, -ch_length},
     237         420 :                  {0.0, -1.0, -ch_length}};
     238             : 
     239         924 :   for (unsigned int i = 0; i < bdry_pars.size(); i++)
     240         768 :     if (trim_peripheral_region[i])
     241             :       try
     242             :       {
     243         517 :         MooseMeshXYCuttingUtils::lineRemoverMoveNode(mesh,
     244             :                                                      bdry_pars[i],
     245             :                                                      block_id_to_remove,
     246             :                                                      subdomain_ids_set,
     247             :                                                      peripheral_trimming_section_boundary_id,
     248             :                                                      external_boundary_id,
     249         517 :                                                      std::vector<boundary_id_type>(),
     250             :                                                      true);
     251             :       }
     252           0 :       catch (MooseException & e)
     253             :       {
     254           0 :         if (((std::string)e.what())
     255           0 :                 .compare("The input mesh has degenerate quad element before trimming.") == 0)
     256           0 :           paramError("input", "The input mesh has degenerate quad element before trimming.");
     257           0 :         else if (((std::string)e.what())
     258           0 :                      .compare("The new subdomain name already exists in the mesh.") == 0)
     259           0 :           paramError("tri_elem_subdomain_name_suffix",
     260             :                      "The new subdomain name already exists in the mesh.");
     261           0 :       }
     262         468 : }

Generated by: LCOV version 1.14