LCOV - code coverage report
Current view: top level - src/meshgenerators - FillBetweenCurvesGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 110 120 91.7 %
Date: 2025-07-17 01:28:37 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       14305 : FillBetweenCurvesGenerator::validParams()
      20             : {
      21       14305 :   InputParameters params = MeshGenerator::validParams();
      22       14305 :   params.addRequiredParam<MeshGeneratorName>("input_mesh_1",
      23             :                                              "The input mesh that contains curve 1");
      24       14305 :   params.addRequiredParam<MeshGeneratorName>("input_mesh_2",
      25             :                                              "The input mesh that contains curve 1");
      26       42915 :   params.addParam<Point>(
      27       28610 :       "mesh_1_shift", Point(0.0, 0.0, 0.0), "Translation vector to be applied to input_mesh_1");
      28       42915 :   params.addParam<Point>(
      29       28610 :       "mesh_2_shift", Point(0.0, 0.0, 0.0), "Translation vector to be applied to input_mesh_2");
      30       14305 :   params.addRequiredRangeCheckedParam<unsigned int>(
      31             :       "num_layers", "num_layers>0", "Number of layers of elements created between the boundaries.");
      32       14305 :   params.addParam<subdomain_id_type>("block_id", 1, "ID to be assigned to the transition layer.");
      33       42915 :   params.addParam<boundary_id_type>(
      34             :       "input_boundary_1_id",
      35       28610 :       10000,
      36             :       "Boundary ID to be assigned to the boundary defined by positions_vector_1.");
      37       42915 :   params.addParam<boundary_id_type>(
      38             :       "input_boundary_2_id",
      39       28610 :       10000,
      40             :       "Boundary ID to be assigned to the boundary defined by positions_vector_2.");
      41       42915 :   params.addParam<boundary_id_type>("begin_side_boundary_id",
      42       28610 :                                     10000,
      43             :                                     "Boundary ID to be assigned to the boundary connecting "
      44             :                                     "starting points of the positions_vectors.");
      45       42915 :   params.addParam<boundary_id_type>("end_side_boundary_id",
      46       28610 :                                     10000,
      47             :                                     "Boundary ID to be assigned to the boundary connecting ending "
      48             :                                     "points of the positions_vectors.");
      49       42915 :   params.addParam<bool>(
      50             :       "use_quad_elements",
      51       28610 :       false,
      52             :       "Whether QUAD4 instead of TRI3 elements are used to construct the transition layer.");
      53       42915 :   params.addRangeCheckedParam<Real>(
      54             :       "bias_parameter",
      55       28610 :       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       42915 :   params.addRangeCheckedParam<Real>(
      61             :       "gaussian_sigma",
      62       28610 :       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       14305 :   params.addClassDescription("This FillBetweenCurvesGenerator object is designed to generate a "
      67             :                              "transition layer to connect two boundaries of two input meshes.");
      68       14305 :   return params;
      69           0 : }
      70             : 
      71          20 : FillBetweenCurvesGenerator::FillBetweenCurvesGenerator(const InputParameters & parameters)
      72             :   : MeshGenerator(parameters),
      73          20 :     _input_name_1(getParam<MeshGeneratorName>("input_mesh_1")),
      74          20 :     _input_name_2(getParam<MeshGeneratorName>("input_mesh_2")),
      75          20 :     _mesh_1_shift(getParam<Point>("mesh_1_shift")),
      76          20 :     _mesh_2_shift(getParam<Point>("mesh_2_shift")),
      77          20 :     _num_layers(getParam<unsigned int>("num_layers")),
      78          20 :     _block_id(getParam<subdomain_id_type>("block_id")),
      79          20 :     _input_boundary_1_id(getParam<boundary_id_type>("input_boundary_1_id")),
      80          20 :     _input_boundary_2_id(getParam<boundary_id_type>("input_boundary_2_id")),
      81          20 :     _begin_side_boundary_id(getParam<boundary_id_type>("begin_side_boundary_id")),
      82          20 :     _end_side_boundary_id(getParam<boundary_id_type>("end_side_boundary_id")),
      83          20 :     _use_quad_elements(getParam<bool>("use_quad_elements")),
      84          20 :     _bias_parameter(getParam<Real>("bias_parameter")),
      85          20 :     _sigma(getParam<Real>("gaussian_sigma")),
      86          20 :     _input_1(getMeshByName(_input_name_1)),
      87          40 :     _input_2(getMeshByName(_input_name_2))
      88             : {
      89          20 :   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          20 : }
      92             : 
      93             : std::unique_ptr<MeshBase>
      94          20 : FillBetweenCurvesGenerator::generate()
      95             : {
      96          20 :   auto input_mesh_1 = dynamic_pointer_cast<ReplicatedMesh>(std::move(_input_1));
      97          20 :   auto input_mesh_2 = dynamic_pointer_cast<ReplicatedMesh>(std::move(_input_2));
      98          20 :   if (!input_mesh_1)
      99           0 :     paramError("input_mesh_1", "Input is not a replicated mesh, which is required.");
     100          20 :   if (!input_mesh_2)
     101           0 :     paramError("input_mesh_2", "Input is not a replicated mesh, which is required.");
     102             : 
     103          20 :   MeshTools::Modification::translate(
     104          20 :       *input_mesh_1, _mesh_1_shift(0), _mesh_1_shift(1), _mesh_1_shift(2));
     105          20 :   MeshTools::Modification::translate(
     106          20 :       *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          20 :   std::vector<dof_id_type> curve_1_ordered_nodes;
     111          20 :   std::vector<dof_id_type> curve_2_ordered_nodes;
     112             : 
     113             :   try
     114             :   {
     115          20 :     FillBetweenPointVectorsTools::isCurveOpenSingleSegment(*input_mesh_1,
     116             :                                                            max_input_mesh_1_node_radius,
     117             :                                                            curve_1_ordered_nodes,
     118          20 :                                                            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          20 :     FillBetweenPointVectorsTools::isCurveOpenSingleSegment(*input_mesh_2,
     128             :                                                            max_input_mesh_2_node_radius,
     129             :                                                            curve_2_ordered_nodes,
     130          20 :                                                            curveCentroidPoint(*input_mesh_2));
     131             :   }
     132           0 :   catch (MooseException & e)
     133             :   {
     134           0 :     paramError("input_mesh_2", e.what());
     135           0 :   }
     136             : 
     137          20 :   std::vector<Point> positions_vector_1;
     138          20 :   std::vector<Point> positions_vector_2;
     139             : 
     140         180 :   for (auto & curve_1_node_id : curve_1_ordered_nodes)
     141         160 :     positions_vector_1.push_back(*input_mesh_1->node_ptr(curve_1_node_id));
     142             : 
     143         140 :   for (auto & curve_2_node_id : curve_2_ordered_nodes)
     144         120 :     positions_vector_2.push_back(*input_mesh_2->node_ptr(curve_2_node_id));
     145             : 
     146          20 :   const boundary_id_type input_boundary_1_id = _input_boundary_1_id;
     147          20 :   const boundary_id_type input_boundary_2_id = _input_boundary_2_id;
     148          20 :   auto mesh = buildReplicatedMesh(2);
     149          20 :   FillBetweenPointVectorsTools::fillBetweenPointVectorsGenerator(*mesh,
     150             :                                                                  positions_vector_1,
     151             :                                                                  positions_vector_2,
     152          20 :                                                                  _num_layers,
     153          20 :                                                                  _block_id,
     154             :                                                                  input_boundary_1_id,
     155             :                                                                  input_boundary_2_id,
     156          20 :                                                                  _begin_side_boundary_id,
     157          20 :                                                                  _end_side_boundary_id,
     158          20 :                                                                  _type,
     159          20 :                                                                  _name,
     160          20 :                                                                  _use_quad_elements,
     161          20 :                                                                  _bias_parameter,
     162          20 :                                                                  _sigma);
     163             : 
     164             :   // Transfer over the nodesets
     165          20 :   BoundaryInfo & boundary = mesh->get_boundary_info();
     166          20 :   const BoundaryInfo & input_bdy_1 = input_mesh_1->get_boundary_info();
     167          20 :   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          20 :   if (!mesh->is_prepared())
     172          20 :     mesh->prepare_for_use();
     173          20 :   auto pl = mesh->sub_point_locator();
     174             : 
     175          20 :   boundary_id_type offset = 0;
     176          20 :   const auto node_list_mesh1 = input_bdy_1.build_node_list();
     177          60 :   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          40 :     boundary.add_node(pl->locate_node(*input_mesh_1->node_ptr(std::get<0>(t))), std::get<1>(t));
     182          40 :     offset = std::max(std::get<1>(t), offset);
     183             :   }
     184             : 
     185          20 :   const auto node_list_mesh2 = input_bdy_2.build_node_list();
     186          80 :   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          60 :     boundary.add_node(pl->locate_node(*input_mesh_2->node_ptr(std::get<0>(t))),
     191          60 :                       std::get<1>(t) + offset);
     192             :   }
     193             : 
     194          30 :   for (const auto & nodeset_pair : input_bdy_1.get_nodeset_name_map())
     195          10 :     boundary.set_nodeset_name_map().insert(nodeset_pair);
     196          30 :   for (const auto & [bnd_id, bnd_name] : input_bdy_2.get_nodeset_name_map())
     197          10 :     boundary.set_nodeset_name_map()[bnd_id + offset] = bnd_name;
     198          20 :   if (node_list_mesh1.size() + node_list_mesh2.size())
     199          10 :     mesh->set_isnt_prepared();
     200             : 
     201          40 :   return dynamic_pointer_cast<MeshBase>(mesh);
     202          20 : }
     203             : 
     204             : Point
     205          40 : FillBetweenCurvesGenerator::curveCentroidPoint(const ReplicatedMesh & curve)
     206             : {
     207          40 :   Point pt_tmp = Point(0.0, 0.0, 0.0);
     208          40 :   Real length_tmp = 0.0;
     209         280 :   for (const auto elem : curve.element_ptr_range())
     210             :   {
     211         240 :     Real elem_length = elem->hmax();
     212         240 :     pt_tmp += (elem->vertex_average()) * elem_length;
     213         240 :     length_tmp += elem_length;
     214          40 :   }
     215          40 :   return pt_tmp / length_tmp;
     216             : }

Generated by: LCOV version 1.14