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 : }