LCOV - code coverage report
Current view: top level - src/meshgenerators - FillBetweenCurvesGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 110 120 91.7 %
Date: 2025-08-08 20:01:16 Functions: 4 4 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 "FillBetweenCurvesGenerator.h"
      11             : #include "FillBetweenPointVectorsTools.h"
      12             : 
      13             : #include "CastUniquePointer.h"
      14             : #include "libmesh/node.h"
      15             : 
      16             : registerMooseObject("MooseApp", FillBetweenCurvesGenerator);
      17             : 
      18             : InputParameters
      19       14309 : FillBetweenCurvesGenerator::validParams()
      20             : {
      21       14309 :   InputParameters params = MeshGenerator::validParams();
      22       14309 :   params.addRequiredParam<MeshGeneratorName>("input_mesh_1",
      23             :                                              "The input mesh that contains curve 1");
      24       14309 :   params.addRequiredParam<MeshGeneratorName>("input_mesh_2",
      25             :                                              "The input mesh that contains curve 1");
      26       42927 :   params.addParam<Point>(
      27       28618 :       "mesh_1_shift", Point(0.0, 0.0, 0.0), "Translation vector to be applied to input_mesh_1");
      28       42927 :   params.addParam<Point>(
      29       28618 :       "mesh_2_shift", Point(0.0, 0.0, 0.0), "Translation vector to be applied to input_mesh_2");
      30       14309 :   params.addRequiredRangeCheckedParam<unsigned int>(
      31             :       "num_layers", "num_layers>0", "Number of layers of elements created between the boundaries.");
      32       14309 :   params.addParam<subdomain_id_type>("block_id", 1, "ID to be assigned to the transition layer.");
      33       42927 :   params.addParam<boundary_id_type>(
      34             :       "input_boundary_1_id",
      35       28618 :       10000,
      36             :       "Boundary ID to be assigned to the boundary defined by positions_vector_1.");
      37       42927 :   params.addParam<boundary_id_type>(
      38             :       "input_boundary_2_id",
      39       28618 :       10000,
      40             :       "Boundary ID to be assigned to the boundary defined by positions_vector_2.");
      41       42927 :   params.addParam<boundary_id_type>("begin_side_boundary_id",
      42       28618 :                                     10000,
      43             :                                     "Boundary ID to be assigned to the boundary connecting "
      44             :                                     "starting points of the positions_vectors.");
      45       42927 :   params.addParam<boundary_id_type>("end_side_boundary_id",
      46       28618 :                                     10000,
      47             :                                     "Boundary ID to be assigned to the boundary connecting ending "
      48             :                                     "points of the positions_vectors.");
      49       42927 :   params.addParam<bool>(
      50             :       "use_quad_elements",
      51       28618 :       false,
      52             :       "Whether QUAD4 instead of TRI3 elements are used to construct the transition layer.");
      53       42927 :   params.addRangeCheckedParam<Real>(
      54             :       "bias_parameter",
      55       28618 :       1.0,
      56             :       "bias_parameter>=0",
      57             :       "Parameter used to set up biasing of the layers: bias_parameter > 0.0 is used as the biasing "
      58             :       "factor; bias_parameter = 0.0 activates automatic biasing based on local node density on "
      59             :       "both input boundaries.");
      60       42927 :   params.addRangeCheckedParam<Real>(
      61             :       "gaussian_sigma",
      62       28618 :       3.0,
      63             :       "gaussian_sigma>0.0",
      64             :       "Gaussian parameter used to smoothen local node density for automatic biasing; this "
      65             :       "parameter is not used if another biasing option is selected.");
      66       14309 :   params.addClassDescription("This FillBetweenCurvesGenerator object is designed to generate a "
      67             :                              "transition layer to connect two boundaries of two input meshes.");
      68       14309 :   return params;
      69           0 : }
      70             : 
      71          22 : FillBetweenCurvesGenerator::FillBetweenCurvesGenerator(const InputParameters & parameters)
      72             :   : MeshGenerator(parameters),
      73          22 :     _input_name_1(getParam<MeshGeneratorName>("input_mesh_1")),
      74          22 :     _input_name_2(getParam<MeshGeneratorName>("input_mesh_2")),
      75          22 :     _mesh_1_shift(getParam<Point>("mesh_1_shift")),
      76          22 :     _mesh_2_shift(getParam<Point>("mesh_2_shift")),
      77          22 :     _num_layers(getParam<unsigned int>("num_layers")),
      78          22 :     _block_id(getParam<subdomain_id_type>("block_id")),
      79          22 :     _input_boundary_1_id(getParam<boundary_id_type>("input_boundary_1_id")),
      80          22 :     _input_boundary_2_id(getParam<boundary_id_type>("input_boundary_2_id")),
      81          22 :     _begin_side_boundary_id(getParam<boundary_id_type>("begin_side_boundary_id")),
      82          22 :     _end_side_boundary_id(getParam<boundary_id_type>("end_side_boundary_id")),
      83          22 :     _use_quad_elements(getParam<bool>("use_quad_elements")),
      84          22 :     _bias_parameter(getParam<Real>("bias_parameter")),
      85          22 :     _sigma(getParam<Real>("gaussian_sigma")),
      86          22 :     _input_1(getMeshByName(_input_name_1)),
      87          44 :     _input_2(getMeshByName(_input_name_2))
      88             : {
      89          22 :   if (_input_name_1.compare(_input_name_2) == 0)
      90           0 :     paramError("input_mesh_2", "This parameter must be different from input_mesh_1.");
      91          22 : }
      92             : 
      93             : std::unique_ptr<MeshBase>
      94          22 : FillBetweenCurvesGenerator::generate()
      95             : {
      96          22 :   auto input_mesh_1 = dynamic_pointer_cast<ReplicatedMesh>(std::move(_input_1));
      97          22 :   auto input_mesh_2 = dynamic_pointer_cast<ReplicatedMesh>(std::move(_input_2));
      98          22 :   if (!input_mesh_1)
      99           0 :     paramError("input_mesh_1", "Input is not a replicated mesh, which is required.");
     100          22 :   if (!input_mesh_2)
     101           0 :     paramError("input_mesh_2", "Input is not a replicated mesh, which is required.");
     102             : 
     103          22 :   MeshTools::Modification::translate(
     104          22 :       *input_mesh_1, _mesh_1_shift(0), _mesh_1_shift(1), _mesh_1_shift(2));
     105          22 :   MeshTools::Modification::translate(
     106          22 :       *input_mesh_2, _mesh_2_shift(0), _mesh_2_shift(1), _mesh_2_shift(2));
     107             : 
     108             :   Real max_input_mesh_1_node_radius;
     109             :   Real max_input_mesh_2_node_radius;
     110          22 :   std::vector<dof_id_type> curve_1_ordered_nodes;
     111          22 :   std::vector<dof_id_type> curve_2_ordered_nodes;
     112             : 
     113             :   try
     114             :   {
     115          22 :     FillBetweenPointVectorsTools::isCurveOpenSingleSegment(*input_mesh_1,
     116             :                                                            max_input_mesh_1_node_radius,
     117             :                                                            curve_1_ordered_nodes,
     118          22 :                                                            curveCentroidPoint(*input_mesh_1));
     119             :   }
     120           0 :   catch (MooseException & e)
     121             :   {
     122           0 :     paramError("input_mesh_1", e.what());
     123           0 :   }
     124             : 
     125             :   try
     126             :   {
     127          22 :     FillBetweenPointVectorsTools::isCurveOpenSingleSegment(*input_mesh_2,
     128             :                                                            max_input_mesh_2_node_radius,
     129             :                                                            curve_2_ordered_nodes,
     130          22 :                                                            curveCentroidPoint(*input_mesh_2));
     131             :   }
     132           0 :   catch (MooseException & e)
     133             :   {
     134           0 :     paramError("input_mesh_2", e.what());
     135           0 :   }
     136             : 
     137          22 :   std::vector<Point> positions_vector_1;
     138          22 :   std::vector<Point> positions_vector_2;
     139             : 
     140         198 :   for (auto & curve_1_node_id : curve_1_ordered_nodes)
     141         176 :     positions_vector_1.push_back(*input_mesh_1->node_ptr(curve_1_node_id));
     142             : 
     143         154 :   for (auto & curve_2_node_id : curve_2_ordered_nodes)
     144         132 :     positions_vector_2.push_back(*input_mesh_2->node_ptr(curve_2_node_id));
     145             : 
     146          22 :   const boundary_id_type input_boundary_1_id = _input_boundary_1_id;
     147          22 :   const boundary_id_type input_boundary_2_id = _input_boundary_2_id;
     148          22 :   auto mesh = buildReplicatedMesh(2);
     149          22 :   FillBetweenPointVectorsTools::fillBetweenPointVectorsGenerator(*mesh,
     150             :                                                                  positions_vector_1,
     151             :                                                                  positions_vector_2,
     152          22 :                                                                  _num_layers,
     153          22 :                                                                  _block_id,
     154             :                                                                  input_boundary_1_id,
     155             :                                                                  input_boundary_2_id,
     156          22 :                                                                  _begin_side_boundary_id,
     157          22 :                                                                  _end_side_boundary_id,
     158          22 :                                                                  _type,
     159          22 :                                                                  _name,
     160          22 :                                                                  _use_quad_elements,
     161          22 :                                                                  _bias_parameter,
     162          22 :                                                                  _sigma);
     163             : 
     164             :   // Transfer over the nodesets
     165          22 :   BoundaryInfo & boundary = mesh->get_boundary_info();
     166          22 :   const BoundaryInfo & input_bdy_1 = input_mesh_1->get_boundary_info();
     167          22 :   const BoundaryInfo & input_bdy_2 = input_mesh_2->get_boundary_info();
     168             : 
     169             :   // Nodes could have been re-ordered during the FillBetweenPointVectors operation
     170             :   // We need to locate the nodes from input nodesets in the new mesh
     171          22 :   if (!mesh->is_prepared())
     172          22 :     mesh->prepare_for_use();
     173          22 :   auto pl = mesh->sub_point_locator();
     174             : 
     175          22 :   boundary_id_type offset = 0;
     176          22 :   const auto node_list_mesh1 = input_bdy_1.build_node_list();
     177          66 :   for (const auto & t : node_list_mesh1)
     178             :   {
     179             :     mooseAssert(pl->locate_node(*input_mesh_1->node_ptr(std::get<0>(t))),
     180             :                 "We should have found the old node in input mesh 1");
     181          44 :     boundary.add_node(pl->locate_node(*input_mesh_1->node_ptr(std::get<0>(t))), std::get<1>(t));
     182          44 :     offset = std::max(std::get<1>(t), offset);
     183             :   }
     184             : 
     185          22 :   const auto node_list_mesh2 = input_bdy_2.build_node_list();
     186          88 :   for (const auto & t : node_list_mesh2)
     187             :   {
     188             :     mooseAssert(pl->locate_node(*input_mesh_1->node_ptr(std::get<0>(t))),
     189             :                 "We should have found the old node in input mesh 2");
     190          66 :     boundary.add_node(pl->locate_node(*input_mesh_2->node_ptr(std::get<0>(t))),
     191          66 :                       std::get<1>(t) + offset);
     192             :   }
     193             : 
     194          33 :   for (const auto & nodeset_pair : input_bdy_1.get_nodeset_name_map())
     195          11 :     boundary.set_nodeset_name_map().insert(nodeset_pair);
     196          33 :   for (const auto & [bnd_id, bnd_name] : input_bdy_2.get_nodeset_name_map())
     197          11 :     boundary.set_nodeset_name_map()[bnd_id + offset] = bnd_name;
     198          22 :   if (node_list_mesh1.size() + node_list_mesh2.size())
     199          11 :     mesh->set_isnt_prepared();
     200             : 
     201          44 :   return dynamic_pointer_cast<MeshBase>(mesh);
     202          22 : }
     203             : 
     204             : Point
     205          44 : FillBetweenCurvesGenerator::curveCentroidPoint(const ReplicatedMesh & curve)
     206             : {
     207          44 :   Point pt_tmp = Point(0.0, 0.0, 0.0);
     208          44 :   Real length_tmp = 0.0;
     209         308 :   for (const auto elem : curve.element_ptr_range())
     210             :   {
     211         264 :     Real elem_length = elem->hmax();
     212         264 :     pt_tmp += (elem->vertex_average()) * elem_length;
     213         264 :     length_tmp += elem_length;
     214          44 :   }
     215          44 :   return pt_tmp / length_tmp;
     216             : }

Generated by: LCOV version 1.14