Cloned SEACAS for EXODUS library with extra build files for internal package management.
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.
 
 
 
 
 
 

423 lines
12 KiB

// Copyright(C) 1999-2022 National Technology & Engineering Solutions
// of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with
// NTESS, the U.S. Government retains certain rights in this software.
//
// See packages/seacas/LICENSE for details
#if defined(EXODUS_SUPPORT)
#include "aprepro.h"
#include "exodusII.h"
#include "apr_symrec.h"
#include "apr_util.h"
#include "aprepro_parser.h"
#include <algorithm>
#include <cctype>
#include <cstdlib>
#include <cstring>
namespace {
std::string LowerCase(std::string name);
bool matches_prefix(const char *pre, const char *str)
{
return strncmp(pre, str, strlen(pre)) == 0;
}
std::string entity_type_name(ex_entity_type ent_type)
{
switch (ent_type) {
case EX_ASSEMBLY: return "assembly_";
case EX_ELEM_BLOCK: return "block_";
case EX_NODE_SET: return "nodeset_";
case EX_SIDE_SET: return "sideset_";
default: return "invalid_";
}
}
void add_name(int exoid, ex_entity_type ent_type, int64_t id, char *name, std::string &names)
{
std::string str_name;
ex_get_name(exoid, ent_type, id, name);
if (name[0] == '\0') {
str_name = entity_type_name(ent_type) + std::to_string(id);
}
else {
str_name = name;
}
if (names.length() > 0) {
names += ",";
}
names += str_name;
}
} // namespace
namespace SEAMS {
extern SEAMS::Aprepro *aprepro;
int open_exodus_file(char *filename)
{
int cpu = sizeof(double);
int io = 0;
float version;
int exo = ex_open(filename, EX_READ | EX_ALL_INT64_API, &cpu, &io, &version);
if (exo < 0) {
// If there is an include path specified, try opening file there
std::string file_path(aprepro->ap_options.include_path);
if (!file_path.empty()) {
file_path += "/";
file_path += filename;
exo = ex_open(file_path.c_str(), EX_READ | EX_ALL_INT64_API, &cpu, &io, &version);
}
if (exo < 0) {
yyerror(*aprepro, "Error opening exodusII file.");
}
}
aprepro->add_variable("ex_version", version);
return exo;
}
const char *do_exodus_info(char *filename, char *prefix)
{
char *ret_string = nullptr;
// Open the specified exodusII file, read the info records
// then parse them as input to aprepro.
int exoid = open_exodus_file(filename);
if (exoid < 0) {
return "";
}
int count = ex_inquire_int(exoid, EX_INQ_INFO);
if (count > 0) {
auto info = new char *[count];
for (int i = 0; i < count; i++) {
info[i] = new char[MAX_LINE_LENGTH + 1];
memset(info[i], '\0', MAX_LINE_LENGTH + 1);
}
ex_get_info(exoid, info);
std::string lines;
size_t prefix_len = strlen(prefix);
for (int i = 0; i < count; i++) {
if (matches_prefix(prefix, info[i])) {
lines += std::string(info[i]).substr(prefix_len);
lines += "\n";
}
}
new_string(lines, &ret_string);
for (int i = 0; i < count; i++) {
delete[] info[i];
}
delete[] info;
ex_close(exoid);
return ret_string;
}
ex_close(exoid);
return "";
}
const char *do_exodus_info_range(char *filename, char *beg, char *end)
{
char *ret_string = nullptr;
// Open the specified exodusII file, read the info records
// then parse them as input to aprepro.
int exoid = open_exodus_file(filename);
if (exoid < 0) {
return "";
}
int count = ex_inquire_int(exoid, EX_INQ_INFO);
if (count > 0) {
auto info = new char *[count];
for (int i = 0; i < count; i++) {
info[i] = new char[MAX_LINE_LENGTH + 1];
memset(info[i], '\0', MAX_LINE_LENGTH + 1);
}
ex_get_info(exoid, info);
bool in_range = false;
std::string lines;
for (int i = 0; i < count; i++) {
if (in_range && strcmp(info[i], end) == 0) {
in_range = false;
}
if (in_range) {
lines += std::string(info[i]);
lines += "\n";
}
if (!in_range && strcmp(info[i], beg) == 0) {
in_range = true;
}
}
new_string(lines, &ret_string);
for (int i = 0; i < count; i++) {
delete[] info[i];
}
delete[] info;
ex_close(exoid);
return ret_string;
}
ex_close(exoid);
return "";
}
const char *do_exodus_meta(char *filename)
{
// Open the specified exodusII file, read the metadata and set
// variables for each item.
// Examples include "node_count", "element_count", ...
int exoid = open_exodus_file(filename);
if (exoid < 0) {
return "";
}
// read database parameters
ex_init_params info;
ex_get_init_ext(exoid, &info);
aprepro->add_variable("ex_title", info.title);
aprepro->add_variable("ex_dimension", info.num_dim);
aprepro->add_variable("ex_node_count", info.num_nodes);
aprepro->add_variable("ex_element_count", info.num_elem);
aprepro->add_variable("ex_block_count", info.num_elem_blk);
aprepro->add_variable("ex_assembly_count", info.num_assembly);
aprepro->add_variable("ex_nodeset_count", info.num_node_sets);
aprepro->add_variable("ex_sideset_count", info.num_side_sets);
{ // Nemesis Information
int proc_count;
int proc_in_file;
char file_type[MAX_STR_LENGTH + 1];
ex_get_init_info(exoid, &proc_count, &proc_in_file, file_type);
if (proc_count > 1) {
int64_t global_nodes;
int64_t global_elements;
int64_t global_blocks;
int64_t global_nsets;
int64_t global_ssets;
aprepro->add_variable("ex_processor_count", proc_count);
ex_get_init_global(exoid, &global_nodes, &global_elements, &global_blocks, &global_nsets,
&global_ssets);
aprepro->add_variable("ex_node_count_global", global_nodes);
aprepro->add_variable("ex_element_count_global", global_elements);
}
}
// Read The Element Blocks, Node Sets, and Side Sets and set variables for each of these.
// The Scheme Is:
// -- 'ex_block_ids' Is an array of the element block ids. (ex_block_count, 1)
// -- 'ex_block_info' is an array of the element block info (id, num_elem, num_node_per_element,
// num_attrib) for each block (ex_block_count,4)
// -- 'ex_nodeset_ids'
// -- 'ex_nodeset_info'
// -- 'ex_sideset_ids'
// -- 'ex_sideset_info'
int max_name_length = ex_inquire_int(exoid, EX_INQ_DB_MAX_USED_NAME_LENGTH);
ex_set_max_name_length(exoid, max_name_length);
char *name = new char[max_name_length + 1];
std::string str_name;
if (info.num_elem_blk > 0) {
auto array_data = aprepro->make_array(info.num_elem_blk, 1);
auto array_block_info = aprepro->make_array(info.num_elem_blk, 4);
std::vector<int64_t> ids(info.num_elem_blk);
ex_get_ids(exoid, EX_ELEM_BLOCK, ids.data());
char type[MAX_STR_LENGTH + 1];
int64_t nel;
int64_t nnel;
int64_t natr;
std::string names;
std::string topology;
int64_t idx = 0;
for (int64_t i = 0; i < info.num_elem_blk; i++) {
ex_get_block(exoid, EX_ELEM_BLOCK, ids[i], type, &nel, &nnel, nullptr, nullptr, &natr);
array_data->data[i] = ids[i];
array_block_info->data[idx++] = ids[i];
array_block_info->data[idx++] = nel;
array_block_info->data[idx++] = nnel;
array_block_info->data[idx++] = natr;
if (i > 0) {
topology += ",";
}
topology += type;
add_name(exoid, EX_ELEM_BLOCK, ids[i], name, names);
}
topology = LowerCase(topology);
aprepro->add_variable("ex_block_topology", topology);
aprepro->add_variable("ex_block_names", names);
aprepro->add_variable("ex_block_ids", array_data);
aprepro->add_variable("ex_block_info", array_block_info);
}
if (info.num_assembly > 0) {
std::vector<int64_t> ids(info.num_assembly);
ex_get_ids(exoid, EX_ASSEMBLY, ids.data());
std::string names;
std::string type;
auto array_data = aprepro->make_array(info.num_assembly, 1);
auto array_info = aprepro->make_array(info.num_assembly, 1);
for (int64_t i = 0; i < info.num_assembly; i++) {
ex_assembly assembly;
assembly.id = ids[i];
assembly.name = new char[max_name_length + 1];
assembly.entity_list = nullptr;
ex_get_assembly(exoid, &assembly);
if (i > 0) {
names += ",";
type += ",";
}
array_data->data[i] = ids[i];
array_info->data[i] = assembly.entity_count;
names += assembly.name;
type += ex_name_of_object(assembly.type);
}
aprepro->add_variable("ex_assembly_type", type);
aprepro->add_variable("ex_assembly_names", names);
aprepro->add_variable("ex_assembly_ids", array_data);
aprepro->add_variable("ex_assembly_info", array_info);
}
// Nodesets...
if (info.num_node_sets > 0) {
auto array_data = aprepro->make_array(info.num_node_sets, 1);
auto array_set_info = aprepro->make_array(info.num_node_sets, 3);
std::vector<int64_t> ids(info.num_node_sets);
ex_get_ids(exoid, EX_NODE_SET, ids.data());
std::string names;
int64_t idx = 0;
for (int64_t i = 0; i < info.num_node_sets; i++) {
int64_t num_entry;
int64_t num_dist;
ex_get_set_param(exoid, EX_NODE_SET, ids[i], &num_entry, &num_dist);
array_data->data[i] = ids[i];
array_set_info->data[idx++] = ids[i];
array_set_info->data[idx++] = num_entry;
array_set_info->data[idx++] = num_dist;
add_name(exoid, EX_NODE_SET, ids[i], name, names);
}
aprepro->add_variable("ex_nodeset_names", names);
aprepro->add_variable("ex_nodeset_ids", array_data);
aprepro->add_variable("ex_nodeset_info", array_set_info);
}
// Sidesets...
if (info.num_side_sets > 0) {
auto array_data = aprepro->make_array(info.num_side_sets, 1);
auto array_set_info = aprepro->make_array(info.num_side_sets, 3);
std::vector<int64_t> ids(info.num_side_sets);
ex_get_ids(exoid, EX_SIDE_SET, ids.data());
std::string names;
int64_t idx = 0;
for (int64_t i = 0; i < info.num_side_sets; i++) {
int64_t num_entry;
int64_t num_dist;
ex_get_set_param(exoid, EX_SIDE_SET, ids[i], &num_entry, &num_dist);
array_data->data[i] = ids[i];
array_set_info->data[idx++] = ids[i];
array_set_info->data[idx++] = num_entry;
array_set_info->data[idx++] = num_dist;
add_name(exoid, EX_SIDE_SET, ids[i], name, names);
}
aprepro->add_variable("ex_sideset_names", names);
aprepro->add_variable("ex_sideset_ids", array_data);
aprepro->add_variable("ex_sideset_info", array_set_info);
}
// Get timestep count
int64_t ts_count = ex_inquire_int(exoid, EX_INQ_TIME);
aprepro->add_variable("ex_timestep_count", ts_count);
if (ts_count > 0) {
std::vector<double> timesteps(ts_count);
ex_get_all_times(exoid, timesteps.data());
auto ts_array_data = aprepro->make_array(ts_count, 1);
for (int64_t i = 0; i < ts_count; i++) {
ts_array_data->data[i] = timesteps[i];
}
aprepro->add_variable("ex_timestep_times", ts_array_data);
}
// See if any global variables on file...
int num_global = 0;
ex_get_variable_param(exoid, EX_GLOBAL, &num_global);
if (num_global > 0) {
std::string names;
for (int i = 0; i < num_global; i++) {
ex_get_variable_name(exoid, EX_GLOBAL, i + 1, name);
if (i > 0) {
names += ",";
}
names += name;
}
aprepro->add_variable("ex_global_var_names", names);
auto glo_array_data = aprepro->make_array(ts_count, num_global);
std::vector<double> globals(num_global);
int index = 0;
for (int64_t i = 0; i < ts_count; i++) {
ex_get_var(exoid, i + 1, EX_GLOBAL, 0, 0, num_global, globals.data());
for (int j = 0; j < num_global; j++) {
glo_array_data->data[index++] = globals[j];
}
}
aprepro->add_variable("ex_global_var_value", glo_array_data);
}
delete[] name;
ex_close(exoid);
return "";
}
} // namespace SEAMS
namespace {
inline int to_lower(int c) { return std::tolower(c); }
std::string LowerCase(std::string name)
{
std::transform(name.begin(), name.end(), name.begin(), to_lower);
return name;
}
} // namespace
#endif