LCOV - code coverage report
Current view: top level - src/meshgenerators - BeamMeshGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/mastodon: 55510a Lines: 58 74 78.4 %
Date: 2025-08-26 23:09:31 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #include "BeamMeshGenerator.h"
       2             : #include "CastUniquePointer.h"
       3             : #include "MooseUtils.h"
       4             : 
       5             : #include <fstream>
       6             : 
       7             : #include "libmesh/replicated_mesh.h"
       8             : #include "libmesh/edge_edge2.h"
       9             : 
      10             : registerMooseObject("MooseApp", BeamMeshGenerator);
      11             : 
      12             : InputParameters
      13          12 : BeamMeshGenerator::validParams()
      14             : {
      15          12 :   InputParameters params = MeshGenerator::validParams();
      16             : 
      17          24 :   params.addRequiredParam<FileName>(
      18             :       "mesh_file",
      19             :       "Mesh file containing node data and element connectivity. Node data should start with header "
      20             :       "`# Nodes` and should contain node id, x, y, z coordinates of the nodes and nodeset ids. "
      21             :       "Each row corresponds to a different node. Element connectivity starts with header `# "
      22             :       "Element Linear` and should contain element id, nodes and block id. Each row corresponds to "
      23             :       "a different element. Currently only linear 1d elements can be generated.");
      24             : 
      25          12 :   return params;
      26           0 : }
      27             : 
      28           6 : BeamMeshGenerator::BeamMeshGenerator(const InputParameters & parameters)
      29          18 :   : MeshGenerator(parameters), _mesh_file(getParam<FileName>("mesh_file"))
      30             : {
      31           6 : }
      32             : 
      33             : std::unique_ptr<MeshBase>
      34           6 : BeamMeshGenerator::generate()
      35             : {
      36           6 :   std::ifstream stream_in(_mesh_file.c_str());
      37             : 
      38           6 :   if (!stream_in)
      39           0 :     paramError("mesh_file", "Can't open beam mesh file: ", _mesh_file);
      40             : 
      41             :   // Find lines starting with "#". This should refer to either Nodes or Element Linear
      42             :   std::string line;
      43             :   std::vector<std::string> file_lines;
      44             :   unsigned int node_start_linenum = std::numeric_limits<unsigned int>::max();
      45             :   unsigned int element_start_linenum = std::numeric_limits<unsigned int>::max();
      46             :   unsigned int node_end_linenum = 0;
      47             :   unsigned int element_end_linenum = 0;
      48             :   unsigned int linenum = 0;
      49             : 
      50          48 :   while (std::getline(stream_in, line))
      51             :   {
      52          42 :     linenum++;
      53             : 
      54          42 :     if (line.find("#") == 0 && line.find("Nodes") != std::string::npos)
      55             :       node_start_linenum = linenum;
      56             : 
      57          42 :     if (line.find("#") == 0 && line.find("Element Linear") != std::string::npos)
      58             :       element_start_linenum = linenum;
      59             : 
      60          48 :     if (line.find("#") == 0 && line.find("Nodes") == std::string::npos &&
      61           6 :         line.find("Element Linear") == std::string::npos)
      62           0 :       mooseError("BeamMeshGenerator: Found a section in the mesh_file that starts with options "
      63             :                  "other than 'Nodes' or 'Element Linear'. Only sections starting with Nodes or "
      64             :                  "Element Linear are "
      65             :                  "currently read by BeamMeshGenerator.");
      66             : 
      67             :     // Store data from file into file_lines
      68          42 :     file_lines.push_back(line);
      69             :   }
      70             : 
      71           6 :   if ((node_start_linenum == std::numeric_limits<unsigned int>::max()) ||
      72           6 :       (element_start_linenum == std::numeric_limits<unsigned int>::max()) ||
      73             :       (node_start_linenum == element_start_linenum))
      74           0 :     mooseError("BeamMeshGenerator: Mesh file should contain separate sections with node and "
      75             :                "element information.");
      76             : 
      77           6 :   std::unique_ptr<ReplicatedMesh> mesh = libmesh_make_unique<ReplicatedMesh>(comm(), 2);
      78             : 
      79           6 :   mesh->set_mesh_dimension(1);
      80           6 :   mesh->set_spatial_dimension(3);
      81             :   BoundaryInfo & boundary_info = mesh->get_boundary_info();
      82             : 
      83           6 :   if (element_start_linenum > node_start_linenum)
      84             :   {
      85             :     // first nodes followed by elements
      86           6 :     node_end_linenum = element_start_linenum - 1;
      87             :     element_end_linenum = linenum;
      88             :   }
      89             :   else
      90             :   {
      91             :     // first elements followed by nodes
      92             :     node_end_linenum = linenum;
      93           0 :     element_end_linenum = node_end_linenum - 1;
      94             :   }
      95             : 
      96             :   // Get node information
      97             :   std::vector<Node *> nodes;
      98             :   std::vector<double> row;
      99             :   unsigned int node_id = 0;
     100          27 :   for (unsigned int i = node_start_linenum; i < node_end_linenum; ++i)
     101             :   {
     102             :     // Ignore empty lines
     103          21 :     if (file_lines[i].empty())
     104           6 :       continue;
     105             : 
     106          15 :     row.clear();
     107          15 :     processLine(file_lines[i], row, i + 1);
     108             : 
     109          15 :     if (row.size() < 3)
     110           0 :       mooseError("BeamMeshGenerator: Each row within the `Nodes` section should atleast contain 4 "
     111             :                  "entries corresponding to node_id, x, y and z coordinate positions. It can "
     112             :                  "additionally contain node sets that the node belongs to.");
     113             : 
     114          15 :     nodes.push_back(mesh->add_point(Point(row[1], row[2], row[3]), node_id));
     115          15 :     if (node_id != row[0])
     116           0 :       mooseError("BeamMeshGenerator: node_id should start at 0 and increase monotonically.");
     117             : 
     118             :     // add node set information
     119          15 :     if (row.size() > 4)
     120             :     {
     121          33 :       for (unsigned int i = 4; i < row.size(); ++i)
     122          18 :         boundary_info.add_node(node_id, int(row[i]));
     123             :     }
     124          15 :     node_id++;
     125             :   }
     126             : 
     127             :   // get element information
     128          15 :   for (unsigned int i = element_start_linenum; i < element_end_linenum; ++i)
     129             :   {
     130             :     // Ignore empty lines
     131           9 :     if (file_lines[i].empty())
     132           0 :       continue;
     133             : 
     134           9 :     row.clear();
     135           9 :     processLine(file_lines[i], row, i + 1);
     136             : 
     137           9 :     if (row.size() != 4)
     138           0 :       mooseError("BeamMeshGenerator: Each row within the `Element_Linear` section should contain "
     139             :                  "only 4 entries corresponding to element_id, node 1, node 2 and block id.");
     140             : 
     141           9 :     if ((row[1] > nodes.size() - 1) || row[2] > nodes.size() - 1)
     142           0 :       mooseError(
     143           0 :           "BeamMeshGenerator: Node id on ", i + 1, " line should not exceed ", nodes.size(), "\n");
     144             : 
     145          18 :     Elem * elem = mesh->add_elem(new Edge2);
     146           9 :     elem->set_node(0) = nodes[row[1]];
     147           9 :     elem->set_node(1) = nodes[row[2]];
     148           9 :     elem->subdomain_id() = row[3];
     149             :   }
     150             : 
     151           6 :   mesh->prepare_for_use(false);
     152             : 
     153          12 :   return dynamic_pointer_cast<MeshBase>(mesh);
     154          12 : }
     155             : 
     156             : void
     157          24 : BeamMeshGenerator::processLine(const std::string & line,
     158             :                                std::vector<double> & row,
     159             :                                const unsigned int & num)
     160             : {
     161             :   // Separate the row and error if it fails
     162          24 :   bool status = MooseUtils::tokenizeAndConvert<double>(line, row, delimiter(line));
     163          24 :   if (!status)
     164           0 :     mooseError("Failed to convert a delimited data into double when reading line ",
     165             :                num,
     166             :                " in file ",
     167           0 :                _mesh_file,
     168             :                ".\n  LINE ",
     169             :                num,
     170             :                ": ",
     171             :                line);
     172          24 : }
     173             : 
     174             : const std::string &
     175          24 : BeamMeshGenerator::delimiter(const std::string & line)
     176             : {
     177          24 :   if (_delimiter.empty())
     178             :   {
     179           6 :     if (line.find(",") != std::string::npos)
     180           6 :       _delimiter = ",";
     181           0 :     else if (line.find("\t") != std::string::npos)
     182           0 :       _delimiter = "\t";
     183             :     else
     184           0 :       _delimiter = " ";
     185             :   }
     186          24 :   return _delimiter;
     187             : }

Generated by: LCOV version 1.14