29 bool MshReader::load(
const std::string &path, Eigen::MatrixXd &vertices, Eigen::MatrixXi &cells, std::vector<std::vector<int>> &elements, std::vector<std::vector<double>> &weights, std::vector<int> &body_ids)
31 std::vector<std::string> node_data_name;
32 std::vector<std::vector<double>> node_data;
34 return load(path, vertices, cells, elements, weights, body_ids, node_data_name, node_data);
37 bool MshReader::load(
const std::string &path, Eigen::MatrixXd &vertices, Eigen::MatrixXi &cells, std::vector<std::vector<int>> &elements, std::vector<std::vector<double>> &weights, std::vector<int> &body_ids, std::vector<std::string> &node_data_name, std::vector<std::vector<double>> &node_data)
39 if (!std::filesystem::exists(path))
41 logger().error(
"Msh file does not exist: {}", path);
48 spec = mshio::load_msh(path);
50 catch (
const std::exception &err)
52 logger().error(
"{}", err.what());
57 logger().error(
"Unknown error while reading MSH file: {}", path);
61 const auto &nodes = spec.nodes;
62 const auto &els = spec.elements;
63 const int n_vertices = nodes.num_nodes;
64 const int max_tag = nodes.max_node_tag;
67 assert(els.entity_blocks.size() > 0);
68 for (
const auto &e : els.entity_blocks)
70 dim = std::max(dim, e.entity_dim);
72 assert(dim == 2 || dim == 3);
74 vertices.resize(n_vertices, dim);
75 std::vector<int> tag_to_index = std::vector<int>(max_tag + 1, -1);
76 if (n_vertices != max_tag)
77 logger().warn(
"MSH file contains more node tags than nodes, condensing nodes which will break input node ordering.");
80 for (
const auto &n : nodes.entity_blocks)
82 for (
int i = 0; i < n.num_nodes_in_block * 3; i += 3)
84 const int node_id = n_vertices != max_tag ? (index++) : (n.tags[i / 3] - 1);
87 vertices.row(node_id) << n.data[i], n.data[i + 1];
89 vertices.row(node_id) << n.data[i], n.data[i + 1], n.data[i + 2];
91 assert(n.tags[i / 3] < tag_to_index.size());
92 tag_to_index[n.tags[i / 3]] = node_id;
98 for (
const auto &e : els.entity_blocks)
100 if (e.entity_dim != dim)
102 const int type = e.element_type;
104 if (type == 2 || type == 9 || type == 21 || type == 23 || type == 25)
106 assert(cells_cols == -1 || cells_cols == 3);
108 num_els += e.num_elements_in_block;
110 else if (type == 3 || type == 10)
112 assert(cells_cols == -1 || cells_cols == 4);
114 num_els += e.num_elements_in_block;
116 else if (type == 4 || type == 11 || type == 29 || type == 30 || type == 31)
118 assert(cells_cols == -1 || cells_cols == 4);
120 num_els += e.num_elements_in_block;
122 else if (type == 5 || type == 12)
124 assert(cells_cols == -1 || cells_cols == 8);
126 num_els += e.num_elements_in_block;
129 assert(cells_cols > 0);
131 std::unordered_map<int, int> entity_tag_to_physical_tag;
137 cells.resize(num_els, cells_cols);
138 body_ids.resize(num_els);
139 elements.resize(num_els);
140 weights.resize(num_els);
142 for (
const auto &e : els.entity_blocks)
144 if (e.entity_dim != dim)
146 const int type = e.element_type;
147 if (type == 2 || type == 9 || type == 21 || type == 23 || type == 25 || type == 3 || type == 10 || type == 4 || type == 11 || type == 29 || type == 30 || type == 31 || type == 5 || type == 12)
149 const size_t n_nodes = mshio::nodes_per_element(type);
150 for (
int i = 0; i < e.data.size(); i += (n_nodes + 1))
153 for (
int j = i + 1; j <= i + cells_cols; ++j)
155 const int v_index = tag_to_index[e.data[j]];
156 assert(v_index < n_vertices);
157 cells(cell_index, index++) = v_index;
160 for (
int j = i + 1; j < i + 1 + n_nodes; ++j)
162 const int v_index = tag_to_index[e.data[j]];
163 assert(v_index < n_vertices);
164 elements[cell_index].push_back(v_index);
167 const auto &it = entity_tag_to_physical_tag.find(e.entity_tag);
168 body_ids[cell_index] =
169 it != entity_tag_to_physical_tag.end() ? it->second : 0;
176 node_data.resize(spec.node_data.size());
178 for (
const auto &data : spec.node_data)
180 for (
const auto &str : data.header.string_tags)
181 node_data_name.push_back(str);
183 for (
const auto &entry : data.entries)
184 for (
const auto &d : entry.data)
185 node_data[i].push_back(d);