You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
222 lines
7.5 KiB
222 lines
7.5 KiB
#include "element_utils.h"
|
|
#include "io_utils.h"
|
|
#include "load_msh_format.h"
|
|
|
|
#include <mshio/MshSpec.h>
|
|
#include <mshio/exception.h>
|
|
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <limits>
|
|
|
|
|
|
namespace mshio {
|
|
|
|
namespace v41 {
|
|
|
|
void load_elements_ascii(std::istream& in, MshSpec& spec)
|
|
{
|
|
Elements& elements = spec.elements;
|
|
in >> elements.num_entity_blocks;
|
|
in >> elements.num_elements;
|
|
in >> elements.min_element_tag;
|
|
in >> elements.max_element_tag;
|
|
assert(in.good());
|
|
|
|
elements.entity_blocks.resize(elements.num_entity_blocks);
|
|
for (size_t i = 0; i < elements.num_entity_blocks; i++) {
|
|
ElementBlock& block = elements.entity_blocks[i];
|
|
|
|
in >> block.entity_dim;
|
|
in >> block.entity_tag;
|
|
in >> block.element_type;
|
|
in >> block.num_elements_in_block;
|
|
|
|
const size_t n = nodes_per_element(block.element_type);
|
|
block.data.resize(block.num_elements_in_block * (n + 1));
|
|
for (size_t j = 0; j < block.num_elements_in_block; j++) {
|
|
for (size_t k = 0; k <= n; k++) {
|
|
in >> block.data[j * (n + 1) + k];
|
|
}
|
|
}
|
|
assert(in.good());
|
|
}
|
|
}
|
|
|
|
void load_elements_binary(std::istream& in, MshSpec& spec)
|
|
{
|
|
eat_white_space(in, 1);
|
|
Elements& elements = spec.elements;
|
|
in.read(reinterpret_cast<char*>(&elements.num_entity_blocks), sizeof(size_t));
|
|
in.read(reinterpret_cast<char*>(&elements.num_elements), sizeof(size_t));
|
|
in.read(reinterpret_cast<char*>(&elements.min_element_tag), sizeof(size_t));
|
|
in.read(reinterpret_cast<char*>(&elements.max_element_tag), sizeof(size_t));
|
|
assert(in.good());
|
|
|
|
elements.entity_blocks.resize(elements.num_entity_blocks);
|
|
for (size_t i = 0; i < elements.num_entity_blocks; i++) {
|
|
ElementBlock& block = elements.entity_blocks[i];
|
|
|
|
in.read(reinterpret_cast<char*>(&block.entity_dim), sizeof(int));
|
|
in.read(reinterpret_cast<char*>(&block.entity_tag), sizeof(int));
|
|
in.read(reinterpret_cast<char*>(&block.element_type), sizeof(int));
|
|
in.read(reinterpret_cast<char*>(&block.num_elements_in_block), sizeof(size_t));
|
|
|
|
const size_t n = nodes_per_element(block.element_type);
|
|
block.data.resize(block.num_elements_in_block * (n + 1));
|
|
in.read(reinterpret_cast<char*>(block.data.data()),
|
|
static_cast<std::streamsize>(sizeof(size_t) * block.data.size()));
|
|
assert(in.good());
|
|
}
|
|
}
|
|
} // namespace v41
|
|
|
|
namespace v22 {
|
|
void load_elements_ascii(std::istream& in, MshSpec& spec)
|
|
{
|
|
Elements& elements = spec.elements;
|
|
size_t num_elements;
|
|
in >> num_elements;
|
|
|
|
// Due to v2.2 constraints, each element is parsed as a separate block, and
|
|
// a regrouping will happen at post-processing time.
|
|
elements.num_entity_blocks += num_elements;
|
|
elements.num_elements += num_elements;
|
|
|
|
int element_num, element_type;
|
|
int num_tags;
|
|
std::vector<int> tags;
|
|
std::vector<int> node_ids;
|
|
|
|
for (size_t i = 0; i < num_elements; i++) {
|
|
in >> element_num;
|
|
in >> element_type;
|
|
in >> num_tags;
|
|
tags.resize(static_cast<size_t>(num_tags));
|
|
for (int j = 0; j < num_tags; j++) {
|
|
in >> tags[static_cast<size_t>(j)];
|
|
}
|
|
|
|
const size_t n = nodes_per_element(element_type);
|
|
node_ids.resize(n);
|
|
for (size_t j = 0; j < n; j++) {
|
|
in >> node_ids[j];
|
|
}
|
|
|
|
elements.min_element_tag =
|
|
std::min(elements.min_element_tag, static_cast<size_t>(element_num));
|
|
elements.max_element_tag =
|
|
std::max(elements.max_element_tag, static_cast<size_t>(element_num));
|
|
|
|
elements.entity_blocks.emplace_back();
|
|
auto& block = elements.entity_blocks.back();
|
|
block.num_elements_in_block = 1;
|
|
block.entity_dim = get_element_dim(element_type);
|
|
if (tags.size() > 0) {
|
|
block.entity_tag = tags.front();
|
|
} else {
|
|
block.entity_tag = 1;
|
|
}
|
|
block.element_type = element_type;
|
|
block.data.resize(n + 1);
|
|
|
|
block.data[0] = static_cast<size_t>(element_num);
|
|
for (size_t j = 0; j < n; j++) {
|
|
block.data[j + 1] = static_cast<size_t>(node_ids[j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void load_elements_binary(std::istream& in, MshSpec& spec)
|
|
{
|
|
Elements& elements = spec.elements;
|
|
in >> elements.num_elements;
|
|
elements.entity_blocks.reserve(elements.num_elements);
|
|
eat_white_space(in, 1);
|
|
|
|
std::vector<int32_t> tags, node_ids;
|
|
int32_t min_tag = std::numeric_limits<int32_t>::max();
|
|
int32_t max_tag = 0;
|
|
size_t num_processed_elements = 0;
|
|
while (num_processed_elements != elements.num_elements) {
|
|
int32_t element_type, num_elements_in_block, num_tags, element_id;
|
|
in.read(reinterpret_cast<char*>(&element_type), 4);
|
|
in.read(reinterpret_cast<char*>(&num_elements_in_block), 4);
|
|
in.read(reinterpret_cast<char*>(&num_tags), 4);
|
|
|
|
tags.resize(static_cast<size_t>(num_tags));
|
|
|
|
const size_t n = nodes_per_element(element_type);
|
|
node_ids.resize(n);
|
|
|
|
// Due to v2.2 constraints, each element is parsed as a separate block, and
|
|
// a regrouping will happen at post-processing time.
|
|
for (size_t i = 0; i < num_elements_in_block; i++) {
|
|
in.read(reinterpret_cast<char*>(&element_id), 4);
|
|
in.read(reinterpret_cast<char*>(tags.data()), 4 * num_tags);
|
|
in.read(reinterpret_cast<char*>(node_ids.data()), static_cast<int>(4 * n));
|
|
|
|
min_tag = std::min(min_tag, element_id);
|
|
max_tag = std::max(max_tag, element_id);
|
|
|
|
elements.entity_blocks.emplace_back();
|
|
ElementBlock& block = elements.entity_blocks.back();
|
|
block.num_elements_in_block = 1;
|
|
block.entity_dim = get_element_dim(element_type);
|
|
if (tags.size() > 0) {
|
|
block.entity_tag = tags.front();
|
|
} else {
|
|
block.entity_tag = 1;
|
|
}
|
|
block.element_type = static_cast<int>(element_type);
|
|
block.data.resize(n + 1);
|
|
|
|
block.data[0] = static_cast<size_t>(element_id);
|
|
for (size_t j = 0; j < n; j++) {
|
|
block.data[j + 1] = static_cast<size_t>(node_ids[j]);
|
|
}
|
|
|
|
num_processed_elements++;
|
|
if (num_processed_elements > elements.num_elements) {
|
|
throw InvalidFormat("Inconsistent element count detected!");
|
|
}
|
|
}
|
|
}
|
|
|
|
elements.num_entity_blocks = elements.entity_blocks.size();
|
|
elements.min_element_tag = std::min(elements.min_element_tag, static_cast<size_t>(min_tag));
|
|
elements.max_element_tag = std::max(elements.max_element_tag, static_cast<size_t>(max_tag));
|
|
}
|
|
|
|
} // namespace v22
|
|
|
|
void load_elements(std::istream& in, MshSpec& spec)
|
|
{
|
|
if (spec.elements.entity_blocks.size() == 0) {
|
|
spec.elements.min_element_tag = std::numeric_limits<size_t>::max();
|
|
spec.elements.max_element_tag = 0;
|
|
}
|
|
|
|
const std::string& version = spec.mesh_format.version;
|
|
const bool is_ascii = spec.mesh_format.file_type == 0;
|
|
if (version == "4.1") {
|
|
if (is_ascii)
|
|
v41::load_elements_ascii(in, spec);
|
|
else
|
|
v41::load_elements_binary(in, spec);
|
|
} else if (version == "2.2") {
|
|
if (is_ascii)
|
|
v22::load_elements_ascii(in, spec);
|
|
else
|
|
v22::load_elements_binary(in, spec);
|
|
} else {
|
|
std::stringstream msg;
|
|
msg << "Unsupported MSH version: " << version;
|
|
throw UnsupportedFeature(msg.str());
|
|
}
|
|
}
|
|
|
|
} // namespace mshio
|
|
|