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.
471 lines
13 KiB
471 lines
13 KiB
// Copyright(C) 1999-2021 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
|
|
|
|
#include "ED_SystemInterface.h"
|
|
#include "exo_entity.h"
|
|
#include "exodusII.h" // for ex_get_var, EX_INVALID_ID, etc
|
|
#include "fmt/color.h"
|
|
#include "fmt/ostream.h"
|
|
#include "smart_assert.h" // for SMART_ASSERT
|
|
#include "stringx.h" // for to_lower
|
|
#include <cstdint> // for int64_t
|
|
#include <cstdlib> // for exit
|
|
#include <cstring> // for strlen
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
size_t get_index(int file_id, EXOTYPE exo_type, size_t id, const char *label);
|
|
size_t get_num_entities(int file_id, EXOTYPE exo_type);
|
|
size_t get_num_variables(int file_id, EXOTYPE type, const char *label);
|
|
size_t get_num_attributes(int file_id, EXOTYPE type, size_t id, const char *label);
|
|
#ifndef NDEBUG
|
|
size_t get_num_timesteps(int file_id);
|
|
#endif
|
|
} // namespace
|
|
|
|
Exo_Entity::Exo_Entity(int file_id, size_t id) : fileId(file_id), id_(id)
|
|
{
|
|
SMART_ASSERT(file_id > 0);
|
|
SMART_ASSERT((int)id > EX_INVALID_ID);
|
|
}
|
|
|
|
Exo_Entity::Exo_Entity(int file_id, size_t id, size_t nnodes)
|
|
: fileId(file_id), id_(id), numEntity(nnodes)
|
|
{
|
|
SMART_ASSERT(file_id > 0);
|
|
SMART_ASSERT((int)id > EX_INVALID_ID);
|
|
}
|
|
|
|
Exo_Entity::~Exo_Entity()
|
|
{
|
|
delete[] truth_;
|
|
if (numVars > 0) {
|
|
for (int i = 0; i < numVars; ++i) {
|
|
delete[] results_[i];
|
|
}
|
|
delete[] results_;
|
|
}
|
|
if (numAttr > 0) {
|
|
for (int i = 0; i < numAttr; ++i) {
|
|
delete[] attributes_[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
int Exo_Entity::Check_State() const
|
|
{
|
|
SMART_ASSERT(id_ >= EX_INVALID_ID);
|
|
|
|
SMART_ASSERT(!(id_ == EX_INVALID_ID && numEntity > 0));
|
|
return 1;
|
|
}
|
|
|
|
void Exo_Entity::initialize(int file_id, size_t id)
|
|
{
|
|
fileId = file_id;
|
|
id_ = id;
|
|
|
|
index_ = get_index(fileId, exodus_type(), id_, label());
|
|
|
|
entity_load_params();
|
|
|
|
internal_load_params();
|
|
}
|
|
|
|
bool Exo_Entity::is_valid_var(size_t var_index) const
|
|
{
|
|
SMART_ASSERT((int)var_index < numVars);
|
|
if (truth_ == nullptr) {
|
|
get_truth_table();
|
|
SMART_ASSERT(truth_ != nullptr);
|
|
}
|
|
|
|
return (truth_[var_index] != 0);
|
|
}
|
|
|
|
std::string Exo_Entity::Load_Results(int time_step, int var_index)
|
|
{
|
|
SMART_ASSERT(Check_State());
|
|
|
|
if (fileId < 0) {
|
|
return "exodiff: ERROR: Invalid file id!";
|
|
}
|
|
if (id_ == EX_INVALID_ID) {
|
|
return "exodiff: ERROR: Must initialize block parameters first!";
|
|
}
|
|
if (var_index < 0 || var_index >= numVars) {
|
|
Error("Exo_Entity::Load_Results(): var_index is invalid. Aborting...\n");
|
|
}
|
|
SMART_ASSERT(time_step >= 1 && time_step <= (int)get_num_timesteps(fileId));
|
|
|
|
if (time_step != currentStep) {
|
|
Free_Results();
|
|
currentStep = time_step;
|
|
}
|
|
|
|
if (truth_ == nullptr) {
|
|
get_truth_table();
|
|
SMART_ASSERT(truth_ != nullptr);
|
|
}
|
|
|
|
if (truth_[var_index] != 0) {
|
|
if ((results_[var_index] == nullptr) && (numEntity != 0u)) {
|
|
results_[var_index] = new double[numEntity];
|
|
SMART_ASSERT(results_[var_index] != nullptr);
|
|
}
|
|
if (numEntity != 0u) {
|
|
int err = 0;
|
|
err = ex_get_var(fileId, time_step, exodus_type(), var_index + 1, id_, numEntity,
|
|
results_[var_index]);
|
|
|
|
if (err < 0) {
|
|
Error(fmt::format("Exo_Entity::Load_Results(): Call to exodus routine"
|
|
" returned error value! {} id = {}\n"
|
|
"Aborting...\n",
|
|
label(), id_));
|
|
}
|
|
else if (err > 0) {
|
|
return fmt::format("WARNING: Number {} returned from call to exodus get variable routine.",
|
|
err);
|
|
}
|
|
}
|
|
else {
|
|
return std::string("WARNING: No items in this ") + label();
|
|
}
|
|
}
|
|
else {
|
|
return std::string("WARNING: Variable not stored in this ") + label();
|
|
}
|
|
return "";
|
|
}
|
|
|
|
std::string Exo_Entity::Load_Results(int t1, int t2, double proportion, int var_index)
|
|
{
|
|
static std::vector<double> results2;
|
|
|
|
SMART_ASSERT(Check_State());
|
|
|
|
if (fileId < 0) {
|
|
return "exodiff: ERROR: Invalid file id!";
|
|
}
|
|
if (id_ == EX_INVALID_ID) {
|
|
return "exodiff: ERROR: Must initialize block parameters first!";
|
|
}
|
|
SMART_ASSERT(var_index >= 0 && var_index < numVars);
|
|
SMART_ASSERT(t1 >= 1 && t1 <= (int)get_num_timesteps(fileId));
|
|
SMART_ASSERT(t2 >= 1 && t2 <= (int)get_num_timesteps(fileId));
|
|
|
|
if (t1 != currentStep) {
|
|
Free_Results();
|
|
currentStep = t1;
|
|
}
|
|
|
|
if (truth_ == nullptr) {
|
|
get_truth_table();
|
|
SMART_ASSERT(truth_ != nullptr);
|
|
}
|
|
|
|
if (truth_[var_index] != 0) {
|
|
if ((results_[var_index] == nullptr) && (numEntity != 0u)) {
|
|
results_[var_index] = new double[numEntity];
|
|
SMART_ASSERT(results_[var_index] != nullptr);
|
|
}
|
|
if (numEntity != 0u) {
|
|
int err =
|
|
ex_get_var(fileId, t1, exodus_type(), var_index + 1, id_, numEntity, results_[var_index]);
|
|
|
|
if (err < 0) {
|
|
Error(fmt::format(
|
|
"Exo_Entity::Load_Results(): Call to exodus routine returned error value! {} id = {}\n"
|
|
"Aborting...\n",
|
|
label(), id_));
|
|
}
|
|
else if (err > 0) {
|
|
return fmt::format("WARNING: Number {} returned from call to exodus get variable routine.",
|
|
err);
|
|
}
|
|
|
|
if (t1 != t2) {
|
|
results2.resize(numEntity);
|
|
err = ex_get_var(fileId, t2, exodus_type(), var_index + 1, id_, numEntity, &results2[0]);
|
|
|
|
if (err < 0) {
|
|
Error(fmt::format("Exo_Entity::Load_Results(): Call to exodus routine"
|
|
" returned error value! {} id = {}\n"
|
|
"Aborting...\n",
|
|
label(), id_));
|
|
}
|
|
|
|
double *results1 = results_[var_index];
|
|
for (size_t i = 0; i < numEntity; i++) {
|
|
results1[i] = (1.0 - proportion) * results1[i] + proportion * results2[i];
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
return std::string("WARNING: No items in this ") + label();
|
|
}
|
|
}
|
|
else {
|
|
return std::string("WARNING: Variable not stored in this ") + label();
|
|
}
|
|
return "";
|
|
}
|
|
|
|
const double *Exo_Entity::Get_Results(int var_index) const
|
|
{
|
|
SMART_ASSERT(Check_State());
|
|
if (currentStep == 0) {
|
|
return nullptr;
|
|
}
|
|
SMART_ASSERT(var_index >= 0 && var_index < numVars);
|
|
if (var_index >= 0 && var_index < numVars) {
|
|
return results_[var_index];
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void Exo_Entity::Free_Results()
|
|
{
|
|
SMART_ASSERT(Check_State());
|
|
|
|
currentStep = 0;
|
|
for (int v = 0; v < numVars; ++v) {
|
|
delete[] results_[v];
|
|
results_[v] = nullptr;
|
|
}
|
|
}
|
|
|
|
void Exo_Entity::get_truth_table() const
|
|
{
|
|
if (numVars > 0 && truth_ == nullptr) {
|
|
truth_ = new int[numVars];
|
|
SMART_ASSERT(truth_ != nullptr);
|
|
// initialize to true for the case of no objects in the block (some older
|
|
// versions of ex_get_object_truth_vector do not set the values at all)
|
|
for (int i = 0; i < numVars; ++i) {
|
|
truth_[i] = 1;
|
|
}
|
|
int err = ex_get_object_truth_vector(fileId, exodus_type(), id_, numVars, truth_);
|
|
if (err < 0) {
|
|
Error("Exo_Entity::get_truth_table(): ex_get_object_truth_vector returned error.\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string Exo_Entity::Load_Attributes(int attr_index)
|
|
{
|
|
SMART_ASSERT(Check_State());
|
|
|
|
if (fileId < 0) {
|
|
return "exodiff: ERROR: Invalid file id!";
|
|
}
|
|
if (id_ == EX_INVALID_ID) {
|
|
return "exodiff: ERROR: Must initialize block parameters first!";
|
|
}
|
|
SMART_ASSERT(attr_index >= 0 && attr_index < numAttr);
|
|
|
|
if ((attributes_[attr_index] == nullptr) && (numEntity != 0u)) {
|
|
attributes_[attr_index] = new double[numEntity];
|
|
SMART_ASSERT(attributes_[attr_index] != nullptr);
|
|
}
|
|
|
|
if (numEntity != 0u) {
|
|
int err = 0;
|
|
err = ex_get_one_attr(fileId, exodus_type(), id_, attr_index + 1, attributes_[attr_index]);
|
|
|
|
if (err < 0) {
|
|
Error(fmt::format("Exo_Entity::Load_Attributes(): Call to exodus routine"
|
|
" returned error value! {} id = {}\n"
|
|
"Aborting...\n",
|
|
label(), id_));
|
|
}
|
|
else if (err > 0) {
|
|
return fmt::format("WARNING: Number {} returned from call to exodus get variable routine.",
|
|
err);
|
|
}
|
|
}
|
|
else {
|
|
return std::string("WARNING: No items in this ") + label();
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
const double *Exo_Entity::Get_Attributes(int attr_index) const
|
|
{
|
|
SMART_ASSERT(Check_State());
|
|
SMART_ASSERT(attr_index >= 0 && attr_index < numAttr);
|
|
return attributes_[attr_index];
|
|
}
|
|
|
|
void Exo_Entity::Free_Attributes()
|
|
{
|
|
SMART_ASSERT(Check_State());
|
|
|
|
for (int v = 0; v < numAttr; ++v) {
|
|
delete[] attributes_[v];
|
|
attributes_[v] = nullptr;
|
|
}
|
|
}
|
|
|
|
const std::string &Exo_Entity::Get_Attribute_Name(int attr_index) const
|
|
{
|
|
SMART_ASSERT(attr_index >= 0 && attr_index < numAttr);
|
|
return attributeNames[attr_index];
|
|
}
|
|
|
|
int Exo_Entity::Find_Attribute_Index(const std::string &name) const
|
|
{
|
|
std::string lower_name = name;
|
|
to_lower(lower_name);
|
|
int indx = -1;
|
|
for (int i = 0; i < numAttr; i++) {
|
|
if (attributeNames[i] == lower_name) {
|
|
indx = i;
|
|
break;
|
|
}
|
|
}
|
|
return indx;
|
|
}
|
|
|
|
void Exo_Entity::internal_load_params()
|
|
{
|
|
int name_size = ex_inquire_int(fileId, EX_INQ_MAX_READ_NAME_LENGTH);
|
|
{
|
|
std::vector<char> name(name_size + 1);
|
|
ex_get_name(fileId, exodus_type(), id_, name.data());
|
|
if (name[0] != '\0') {
|
|
name_ = name.data();
|
|
to_lower(name_);
|
|
}
|
|
else {
|
|
name_ = short_label();
|
|
name_ += "_";
|
|
name_ += std::to_string(id_);
|
|
}
|
|
}
|
|
numVars = get_num_variables(fileId, exodus_type(), label());
|
|
if (numVars != 0) {
|
|
results_ = new double *[numVars];
|
|
SMART_ASSERT(results_ != nullptr);
|
|
for (int i = 0; i < numVars; ++i) {
|
|
results_[i] = nullptr;
|
|
}
|
|
}
|
|
|
|
numAttr = get_num_attributes(fileId, exodus_type(), id_, label());
|
|
if (numAttr != 0) {
|
|
attributes_.resize(numAttr);
|
|
|
|
char **names = get_name_array(numAttr, name_size);
|
|
int err = ex_get_attr_names(fileId, exodus_type(), id_, names);
|
|
if (err < 0) {
|
|
Error(fmt::format(
|
|
"ExoII_Read::Get_Init_Data(): Failed to get {} attribute names! Aborting...\n",
|
|
label()));
|
|
}
|
|
|
|
for (int vg = 0; vg < numAttr; ++vg) {
|
|
SMART_ASSERT(names[vg] != nullptr);
|
|
if (std::strlen(names[vg]) == 0) {
|
|
std::string name = "attribute_" + std::to_string(vg + 1);
|
|
attributeNames.push_back(name);
|
|
}
|
|
else if (static_cast<int>(std::strlen(names[vg])) > name_size) {
|
|
fmt::print(stderr, fmt::fg(fmt::color::red),
|
|
"exodiff: ERROR: {} attribute names appear corrupt\n"
|
|
" A length is 0 or greater than name_size({})\n"
|
|
" Here are the names that I received from"
|
|
" a call to ex_get_attr_names(...):\n",
|
|
label(), name_size);
|
|
for (int k = 1; k <= numAttr; ++k) {
|
|
fmt::print(stderr, fmt::fg(fmt::color::red), "\t\t{}) \"{}\"\n", k, names[k - 1]);
|
|
}
|
|
fmt::print(stderr, fmt::fg(fmt::color::red), " Aborting...\n");
|
|
exit(1);
|
|
}
|
|
else {
|
|
std::string n(names[vg]);
|
|
to_lower(n);
|
|
attributeNames.push_back(n);
|
|
}
|
|
}
|
|
free_name_array(names, numAttr);
|
|
}
|
|
}
|
|
|
|
namespace {
|
|
size_t get_index(int file_id, EXOTYPE exo_type, size_t id, const char *label)
|
|
{
|
|
// Get ids...
|
|
size_t count = get_num_entities(file_id, exo_type);
|
|
if ((ex_int64_status(file_id) & EX_IDS_INT64_API) != 0) {
|
|
std::vector<int64_t> ids(count);
|
|
ex_get_ids(file_id, exo_type, ids.data());
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
|
if (static_cast<size_t>(ids[i]) == id) {
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
std::vector<int> ids(count);
|
|
ex_get_ids(file_id, exo_type, ids.data());
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
|
if (static_cast<size_t>(ids[i]) == id) {
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
|
|
Error(fmt::format("{} id {} does not exist!\n", label, id));
|
|
return 0;
|
|
}
|
|
|
|
size_t get_num_entities(int file_id, EXOTYPE exo_type)
|
|
{
|
|
ex_inquiry inquiry = EX_INQ_INVALID;
|
|
switch (exo_type) {
|
|
case EX_ELEM_BLOCK: inquiry = EX_INQ_ELEM_BLK; break;
|
|
case EX_NODE_SET: inquiry = EX_INQ_NODE_SETS; break;
|
|
case EX_SIDE_SET: inquiry = EX_INQ_SIDE_SETS; break;
|
|
case EX_EDGE_BLOCK: inquiry = EX_INQ_EDGE_BLK; break;
|
|
case EX_FACE_BLOCK: inquiry = EX_INQ_FACE_BLK; break;
|
|
default: Error("Invalid entity type in get_num_entities\n");
|
|
}
|
|
SMART_ASSERT(inquiry != EX_INQ_INVALID);
|
|
return ex_inquire_int(file_id, inquiry);
|
|
}
|
|
|
|
size_t get_num_variables(int file_id, EXOTYPE type, const char *label)
|
|
{
|
|
int num_vars = 0;
|
|
int err = ex_get_variable_param(file_id, type, &num_vars);
|
|
if (err < 0) {
|
|
Error(fmt::format("Failed to get number of '{}' variables! Aborting...\n", label));
|
|
}
|
|
return num_vars;
|
|
}
|
|
|
|
size_t get_num_attributes(int file_id, EXOTYPE type, size_t id, const char *label)
|
|
{
|
|
int num_attr = 0;
|
|
int err = ex_get_attr_param(file_id, type, id, &num_attr);
|
|
if (err < 0) {
|
|
Error(fmt::format("Failed to get number of '{}' attributes! Aborting...\n", label));
|
|
}
|
|
return num_attr;
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
size_t get_num_timesteps(int file_id) { return ex_inquire_int(file_id, EX_INQ_TIME); }
|
|
#endif
|
|
} // namespace
|
|
|