LCOV - code coverage report
Current view: top level - src/meshgenerators - FillBetweenSidesetsGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 120 130 92.3 %
Date: 2025-07-17 01:28:37 Functions: 3 3 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 "FillBetweenSidesetsGenerator.h"
      11             : #include "FillBetweenPointVectorsTools.h"
      12             : 
      13             : #include "MooseMeshUtils.h"
      14             : #include "CastUniquePointer.h"
      15             : #include "libmesh/node.h"
      16             : #include "libmesh/mesh_serializer.h"
      17             : 
      18             : registerMooseObject("MooseApp", FillBetweenSidesetsGenerator);
      19             : 
      20             : InputParameters
      21       14433 : FillBetweenSidesetsGenerator::validParams()
      22             : {
      23       14433 :   InputParameters params = MeshGenerator::validParams();
      24       14433 :   params.addRequiredParam<MeshGeneratorName>("input_mesh_1",
      25             :                                              "The input mesh that contains boundary_1");
      26       14433 :   params.addRequiredParam<MeshGeneratorName>("input_mesh_2",
      27             :                                              "The input mesh that contains boundary_2");
      28       14433 :   params.addRequiredParam<std::vector<BoundaryName>>(
      29             :       "boundary_1", "the first boundary that needs to be connected.");
      30       14433 :   params.addRequiredParam<std::vector<BoundaryName>>(
      31             :       "boundary_2", "the second boundary that needs to be connected.");
      32       43299 :   params.addParam<Point>(
      33       28866 :       "mesh_1_shift", Point(0.0, 0.0, 0.0), "Translation vector to be applied to input_mesh_1");
      34       43299 :   params.addParam<Point>(
      35       28866 :       "mesh_2_shift", Point(0.0, 0.0, 0.0), "Translation vector to be applied to input_mesh_2");
      36       14433 :   params.addRequiredRangeCheckedParam<unsigned int>(
      37             :       "num_layers", "num_layers>0", "Number of layers of elements created between the boundaries.");
      38       14433 :   params.addParam<subdomain_id_type>("block_id", 1, "ID to be assigned to the transition layer.");
      39       43299 :   params.addParam<boundary_id_type>(
      40             :       "input_boundary_1_id",
      41       28866 :       10000,
      42             :       "Boundary ID to be assigned to the boundary defined by positions_vector_1.");
      43       43299 :   params.addParam<boundary_id_type>(
      44             :       "input_boundary_2_id",
      45       28866 :       10000,
      46             :       "Boundary ID to be assigned to the boundary defined by positions_vector_2.");
      47       43299 :   params.addParam<boundary_id_type>("begin_side_boundary_id",
      48       28866 :                                     10000,
      49             :                                     "Boundary ID to be assigned to the boundary connecting "
      50             :                                     "starting points of the positions_vectors.");
      51       43299 :   params.addParam<boundary_id_type>("end_side_boundary_id",
      52       28866 :                                     10000,
      53             :                                     "Boundary ID to be assigned to the boundary connecting ending "
      54             :                                     "points of the positions_vectors.");
      55       43299 :   params.addParam<bool>(
      56             :       "use_quad_elements",
      57       28866 :       false,
      58             :       "Whether QUAD4 instead of TRI3 elements are used to construct the transition layer.");
      59       43299 :   params.addRangeCheckedParam<Real>(
      60             :       "bias_parameter",
      61       28866 :       1.0,
      62             :       "bias_parameter>=0",
      63             :       "Parameter used to set up biasing of the layers: bias_parameter > 0.0 is used as the biasing "
      64             :       "factor; bias_parameter = 0.0 activates automatic biasing based on local node density on "
      65             :       "both input boundaries.");
      66       43299 :   params.addRangeCheckedParam<Real>(
      67             :       "gaussian_sigma",
      68       28866 :       3.0,
      69             :       "gaussian_sigma>0.0",
      70             :       "Gaussian parameter used to smoothen local node density for automatic biasing; this "
      71             :       "parameter is not used if another biasing option is selected.");
      72       43299 :   params.addParam<bool>(
      73             :       "keep_inputs",
      74       28866 :       true,
      75             :       "Whether to output the input meshes stitched with the transition layer connector.");
      76       14433 :   params.addClassDescription("This FillBetweenSidesetsGenerator object is designed to generate a "
      77             :                              "transition layer to connect two boundaries of two input meshes.");
      78       14433 :   return params;
      79           0 : }
      80             : 
      81          86 : FillBetweenSidesetsGenerator::FillBetweenSidesetsGenerator(const InputParameters & parameters)
      82             :   : MeshGenerator(parameters),
      83          86 :     _input_name_1(getParam<MeshGeneratorName>("input_mesh_1")),
      84          86 :     _input_name_2(getParam<MeshGeneratorName>("input_mesh_2")),
      85          86 :     _boundary_1(getParam<std::vector<BoundaryName>>("boundary_1")),
      86          86 :     _boundary_2(getParam<std::vector<BoundaryName>>("boundary_2")),
      87          86 :     _mesh_1_shift(getParam<Point>("mesh_1_shift")),
      88          86 :     _mesh_2_shift(getParam<Point>("mesh_2_shift")),
      89          86 :     _num_layers(getParam<unsigned int>("num_layers")),
      90          86 :     _block_id(getParam<subdomain_id_type>("block_id")),
      91          86 :     _input_boundary_1_id(getParam<boundary_id_type>("input_boundary_1_id")),
      92          86 :     _input_boundary_2_id(getParam<boundary_id_type>("input_boundary_2_id")),
      93          86 :     _begin_side_boundary_id(getParam<boundary_id_type>("begin_side_boundary_id")),
      94          86 :     _end_side_boundary_id(getParam<boundary_id_type>("end_side_boundary_id")),
      95          86 :     _use_quad_elements(getParam<bool>("use_quad_elements")),
      96          86 :     _bias_parameter(getParam<Real>("bias_parameter")),
      97          86 :     _sigma(getParam<Real>("gaussian_sigma")),
      98          86 :     _keep_inputs(getParam<bool>("keep_inputs")),
      99          86 :     _input_1(getMeshByName(_input_name_1)),
     100         172 :     _input_2(getMeshByName(_input_name_2))
     101             : {
     102          86 :   if (_input_name_1.compare(_input_name_2) == 0)
     103           4 :     paramError("input_mesh_2", "This parameter must be different from input_mesh_1.");
     104          82 : }
     105             : 
     106             : std::unique_ptr<MeshBase>
     107          79 : FillBetweenSidesetsGenerator::generate()
     108             : {
     109          79 :   auto input_mesh_1 = std::move(_input_1);
     110          79 :   auto input_mesh_2 = std::move(_input_2);
     111             : 
     112             :   // Only serialized meshes are supported right now
     113          79 :   libMesh::MeshSerializer serial_1(*input_mesh_1);
     114          79 :   libMesh::MeshSerializer serial_2(*input_mesh_2);
     115             : 
     116         158 :   if (*(input_mesh_1->elem_dimensions().begin()) != 2 ||
     117         158 :       *(input_mesh_1->elem_dimensions().rbegin()) != 2)
     118           0 :     paramError("input_mesh_1", "Only 2D meshes are supported.");
     119         158 :   if (*(input_mesh_2->elem_dimensions().begin()) != 2 ||
     120         158 :       *(input_mesh_2->elem_dimensions().rbegin()) != 2)
     121           0 :     paramError("input_mesh_2", "Only 2D meshes are supported.");
     122             : 
     123          79 :   MeshTools::Modification::translate(
     124          79 :       *input_mesh_1, _mesh_1_shift(0), _mesh_1_shift(1), _mesh_1_shift(2));
     125          79 :   MeshTools::Modification::translate(
     126          79 :       *input_mesh_2, _mesh_2_shift(0), _mesh_2_shift(1), _mesh_2_shift(2));
     127             : 
     128             :   const auto input_mesh_1_external_bids =
     129          79 :       MooseMeshUtils::getBoundaryIDs(*input_mesh_1, _boundary_1, false);
     130             :   const auto input_mesh_2_external_bids =
     131          79 :       MooseMeshUtils::getBoundaryIDs(*input_mesh_2, _boundary_2, false);
     132             : 
     133         127 :   for (unsigned int i = 1; i < input_mesh_1_external_bids.size(); i++)
     134             :   {
     135          48 :     MooseMeshUtils::changeBoundaryId(
     136          48 :         *input_mesh_1, input_mesh_1_external_bids[i], input_mesh_1_external_bids.front(), true);
     137             :   }
     138         119 :   for (unsigned int i = 1; i < input_mesh_2_external_bids.size(); i++)
     139             :   {
     140          40 :     MooseMeshUtils::changeBoundaryId(
     141          40 :         *input_mesh_2, input_mesh_2_external_bids[i], input_mesh_2_external_bids.front(), true);
     142             :   }
     143             : 
     144          79 :   if (!FillBetweenPointVectorsTools::isExternalBoundary(*input_mesh_1,
     145          79 :                                                         input_mesh_1_external_bids.front()))
     146           0 :     paramError("boundary_1", "The boundary provided is not an external boundary.");
     147          79 :   if (!FillBetweenPointVectorsTools::isExternalBoundary(*input_mesh_2,
     148          79 :                                                         input_mesh_2_external_bids.front()))
     149           0 :     paramError("boundary_2", "The boundary provided is not an external boundary.");
     150             : 
     151             :   Real max_input_mesh_1_node_radius;
     152             :   Real max_input_mesh_2_node_radius;
     153          79 :   std::vector<dof_id_type> boundary_1_ordered_nodes;
     154          79 :   std::vector<dof_id_type> boundary_2_ordered_nodes;
     155             : 
     156             :   try
     157             :   {
     158         158 :     FillBetweenPointVectorsTools::isBoundaryOpenSingleSegment(
     159          79 :         *input_mesh_1,
     160             :         max_input_mesh_1_node_radius,
     161             :         boundary_1_ordered_nodes,
     162          79 :         MooseMeshUtils::meshCentroidCalculator(*input_mesh_1),
     163          79 :         input_mesh_1_external_bids.front());
     164             :   }
     165           8 :   catch (MooseException & e)
     166             :   {
     167           8 :     paramError("boundary_1", e.what());
     168           0 :   }
     169             :   try
     170             :   {
     171         142 :     FillBetweenPointVectorsTools::isBoundaryOpenSingleSegment(
     172          71 :         *input_mesh_2,
     173             :         max_input_mesh_2_node_radius,
     174             :         boundary_2_ordered_nodes,
     175          71 :         MooseMeshUtils::meshCentroidCalculator(*input_mesh_2),
     176          71 :         input_mesh_2_external_bids.front());
     177             :   }
     178           0 :   catch (MooseException & e)
     179             :   {
     180           0 :     paramError("boundary_2", e.what());
     181           0 :   }
     182             : 
     183          71 :   std::vector<Point> positions_vector_1;
     184          71 :   std::vector<Point> positions_vector_2;
     185             : 
     186         620 :   for (auto & boundary_1_node_id : boundary_1_ordered_nodes)
     187         549 :     positions_vector_1.push_back(*input_mesh_1->node_ptr(boundary_1_node_id));
     188             : 
     189         748 :   for (auto & boundary_2_node_id : boundary_2_ordered_nodes)
     190         677 :     positions_vector_2.push_back(*input_mesh_2->node_ptr(boundary_2_node_id));
     191             : 
     192           0 :   const boundary_id_type input_boundary_1_id = _keep_inputs ? (std::max({_input_boundary_1_id,
     193          34 :                                                                          _input_boundary_2_id,
     194          34 :                                                                          _begin_side_boundary_id,
     195          34 :                                                                          _end_side_boundary_id}) +
     196             :                                                                1)
     197         105 :                                                             : _input_boundary_1_id;
     198          37 :   const boundary_id_type input_boundary_2_id =
     199          71 :       _keep_inputs ? (input_boundary_1_id + 1) : _input_boundary_2_id;
     200          71 :   auto mesh = buildReplicatedMesh(2);
     201          71 :   FillBetweenPointVectorsTools::fillBetweenPointVectorsGenerator(*mesh,
     202             :                                                                  positions_vector_1,
     203             :                                                                  positions_vector_2,
     204          71 :                                                                  _num_layers,
     205          71 :                                                                  _block_id,
     206             :                                                                  input_boundary_1_id,
     207             :                                                                  input_boundary_2_id,
     208          71 :                                                                  _begin_side_boundary_id,
     209          71 :                                                                  _end_side_boundary_id,
     210          71 :                                                                  _type,
     211          71 :                                                                  _name,
     212          71 :                                                                  _use_quad_elements,
     213          71 :                                                                  _bias_parameter,
     214          71 :                                                                  _sigma);
     215             : 
     216          71 :   if (_keep_inputs)
     217             :   {
     218          34 :     mesh->prepare_for_use();
     219          68 :     mesh->stitch_meshes(*input_mesh_1,
     220             :                         input_boundary_1_id,
     221          34 :                         input_mesh_1_external_bids.front(),
     222             :                         TOLERANCE,
     223             :                         true,
     224             :                         false,
     225             :                         true,
     226             :                         true);
     227          68 :     mesh->stitch_meshes(*input_mesh_2,
     228             :                         input_boundary_2_id,
     229          34 :                         input_mesh_2_external_bids.front(),
     230             :                         TOLERANCE,
     231             :                         true,
     232             :                         false,
     233             :                         true,
     234             :                         true);
     235             :   }
     236         142 :   return dynamic_pointer_cast<MeshBase>(mesh);
     237          71 : }

Generated by: LCOV version 1.14