void Ioss::ParallelUtils::global_array_minmax(double *local_minmax, size_t count, Ioss::ParallelUtils::MinMax which) const { #ifdef HAVE_MPI if (parallel_size() > 1 && count > 0) { if (Ioss::SerializeIO::isEnabled() && Ioss::SerializeIO::inBarrier()) { std::ostringstream errmsg; errmsg << "Attempting mpi while in barrier owned by " << Ioss::SerializeIO::getOwner(); IOSS_ERROR(errmsg); } std::vector<double> maxout(count); MPI_Op oper; if (which == DO_MAX) oper = MPI_MAX; else oper = MPI_MIN; const int success = MPI_Allreduce((void*)&local_minmax[0], &maxout[0], static_cast<int>(count), MPI_DOUBLE, oper, communicator_); if (success != MPI_SUCCESS) { std::ostringstream errmsg; errmsg << "Ioss::ParallelUtils::global_array_minmax - MPI_Allreduce failed"; IOSS_ERROR(errmsg); } // Now copy back into passed in array... for (size_t i=0; i < count; i++) { local_minmax[i] = maxout[i]; } } #endif }
int64_t Ioex::SuperElement::internal_get_field_data(const Ioss::Field& field, void *data, size_t data_size) const { size_t num_to_get = field.verify(data_size); assert(num_to_get == numDOF * numDOF); if (field.get_name() == "Kr") { int status = nc_get_array(filePtr, "Kr", (double*)data); if (status != 0) { std::ostringstream errmsg; errmsg << "ERROR: Could not load stiffness matrix field 'Kr' from file '" << fileName << "'."; IOSS_ERROR(errmsg); } } else if (field.get_name() == "Mr") { int status = nc_get_array(filePtr, "Mr", (double*)data); if (status != 0) { std::ostringstream errmsg; errmsg << "ERROR: Could not load mass matrix field 'Mr' from file '" << fileName << "'."; IOSS_ERROR(errmsg); } } else { std::cerr << "WARNING: " << type() << " '" << name() << "'. Unknown input field '" << field.get_name() << "'"; return -4; } return num_to_get; }
unsigned int Ioss::ParallelUtils::global_minmax(unsigned int local_minmax, Ioss::ParallelUtils::MinMax which) const { unsigned int minmax = local_minmax; #ifdef HAVE_MPI if (parallel_size() > 1) { if (Ioss::SerializeIO::isEnabled() && Ioss::SerializeIO::inBarrier()) { std::ostringstream errmsg; errmsg << "Attempting mpi while in barrier owned by " << Ioss::SerializeIO::getOwner(); IOSS_ERROR(errmsg); } static unsigned int inbuf[1], outbuf[1]; inbuf[0] = local_minmax; MPI_Op oper; if (which == DO_MAX) oper = MPI_MAX; else oper = MPI_MIN; const int success = MPI_Allreduce((void*)&inbuf[0], &outbuf[0], 1, MPI_UNSIGNED, oper, communicator_); if (success != MPI_SUCCESS) { std::ostringstream errmsg; errmsg << "Ioss::ParallelUtils::global_minmax - MPI_Allreduce failed"; IOSS_ERROR(errmsg); } minmax = outbuf[0]; } #endif return minmax; }
void Ioss::ParallelUtils::global_count(const Int64Vector &local_counts, Int64Vector &global_counts) const { // Vector 'local_counts' contains the number of objects // local to this processor. On exit, global_counts // contains the total number of objects on all processors. // Assumes that ordering is the same on all processors global_counts.resize(local_counts.size()); #ifdef HAVE_MPI if (local_counts.size() > 0 && parallel_size() > 1) { if (Ioss::SerializeIO::isEnabled() && Ioss::SerializeIO::inBarrier()) { std::ostringstream errmsg; errmsg << "Attempting mpi while in barrier owned by " << Ioss::SerializeIO::getOwner(); IOSS_ERROR(errmsg); } const int success = MPI_Allreduce((void*)&local_counts[0], &global_counts[0], static_cast<int>(local_counts.size()), MPI_LONG_LONG_INT, MPI_SUM, communicator_); if (success != MPI_SUCCESS) { std::ostringstream errmsg; errmsg << "Ioss::ParallelUtils::global_count - MPI_Allreduce failed"; IOSS_ERROR(errmsg); } } else { // Serial run, just copy local to global... std::copy(local_counts.begin(), local_counts.end(), global_counts.begin()); } #else std::copy(local_counts.begin(), local_counts.end(), global_counts.begin()); #endif }
SerializeIO::SerializeIO( const DatabaseIO *database_io, int manual_owner_processor) : m_databaseIO(database_io), m_activeFallThru(s_owner != -1) { const Ioss::ParallelUtils util = m_databaseIO->util(); if (s_rank == -1) { s_rank = util.parallel_rank(); s_size = util.parallel_size(); if (s_groupFactor != 0) { s_groupRank = s_rank/s_groupFactor; s_groupSize = (s_size - 1)/s_groupFactor + 1; } } m_manualOwner = (manual_owner_processor == -1 || s_groupFactor == 0) ? -1 : manual_owner_processor/s_groupFactor; if (m_activeFallThru) { if (m_manualOwner != -1 && m_manualOwner != s_owner) { std::ostringstream errmsg; errmsg << "Attempting to replace manual ownership from " << s_owner << " to " << m_manualOwner; IOSS_ERROR(errmsg); } } else if (s_groupFactor > 0) { if (m_manualOwner == -1) { #ifdef HAVE_MPI do { MPI_Barrier(util.communicator()); } while (++s_owner != s_groupRank); #endif m_databaseIO->openDatabase(); } else { if (s_owner != -1 && m_manualOwner != s_owner) { std::ostringstream errmsg; errmsg << "Attempting to replace manual ownership from " << s_owner << " to " << m_manualOwner; IOSS_ERROR(errmsg); } s_owner = m_manualOwner; } } else { s_owner = s_groupRank; } }
std::string Ioss::VariableType::numeric_label(int which, int ncomp, const std::string &name) { char digits[8]; // Create a format for our use... char format[5]; if (ncomp < 10) std::strcpy(format, "%01d"); else if (ncomp < 100) std::strcpy(format, "%02d"); else if (ncomp < 1000) std::strcpy(format, "%03d"); else if (ncomp < 10000) std::strcpy(format, "%04d"); else if (ncomp < 100000) std::strcpy(format, "%05d"); else { std::ostringstream errmsg; errmsg << "ERROR: Variable '" << name << "' has " << ncomp << " components which is larger than the current maximum" << " of 100,000. Please contact developer.\n"; IOSS_ERROR(errmsg); } std::sprintf(digits, format, which); return std::string(digits); }
const Ioss::VariableType* Ioss::VariableType::factory(const std::string& raw_name, int copies) { Ioss::VariableType* inst = NULL; std::string name = Ioss::Utils::lowercase(raw_name); Ioss::VariableTypeMap::iterator iter = registry().find(name); if (iter == registry().end()) { bool can_construct = build_variable_type(name); if (can_construct) { iter = registry().find(name); assert(iter != registry().end()); inst = (*iter).second; } else { std::ostringstream errmsg; errmsg << "FATAL: The variable type '" << raw_name << "' is not supported.\n"; IOSS_ERROR(errmsg); } } else { inst = (*iter).second; } if (copies != 1) { inst = CompositeVariableType::composite_variable_type(inst, copies); } assert(inst != NULL); return inst; }
void DatabaseIO::create_groups(const std::string &property_name, EntityType type, const std::string &type_name, const T *set_type) { if (!properties.exists(property_name)) { return; } std::string prop = properties.get(property_name).get_string(); std::vector<std::string> groups = tokenize(prop, ":"); for (auto &group : groups) { std::vector<std::string> group_spec = tokenize(group, ","); // group_spec should contain the name of the new group as // the first location and the members of the group as subsequent // locations. OK to have a single member if (group_spec.size() < 2) { std::ostringstream errmsg; errmsg << "ERROR: Invalid " << type_name << " group specification '" << group << "'\n" << " Correct syntax is 'new_group,member1,...,memberN' and " "their must " << " be at least 1 member of the group"; IOSS_ERROR(errmsg); } create_group(type, type_name, group_spec, set_type); } }
Ioss::EntityBlock::EntityBlock(Ioss::DatabaseIO *io_database, const std::string &my_name, const std::string &entity_type, size_t entity_count) : Ioss::GroupingEntity(io_database, my_name, entity_count), idOffset(0) { // The 'true' means it is ok for the factory to return // nullptr. This is done here just so we can output a better // error message. topology_ = ElementTopology::factory(entity_type, true); if (topology_ == nullptr) { std::ostringstream errmsg; errmsg << "ERROR: The topology type '" << entity_type << "' is not supported" << " on " << name() << " in file " << io_database->get_filename(); IOSS_ERROR(errmsg); } if (topology()->master_element_name() != entity_type && topology()->name() != entity_type) { // Maintain original element type on output database if possible. properties.add(Ioss::Property("original_topology_type", entity_type)); } properties.add(Ioss::Property(this, "topology_node_count", Ioss::Property::INTEGER)); properties.add(Ioss::Property(this, "topology_type", Ioss::Property::STRING)); fields.add(Ioss::Field("connectivity", field_int_type(), topology_->name(), Ioss::Field::MESH, entity_count)); // Returns connectivity in local id space fields.add(Ioss::Field("connectivity_raw", field_int_type(), topology()->name(), Ioss::Field::MESH, entity_count)); }
void Ioss::ParallelUtils::attribute_reduction( const int length , char buffer[]) const { #ifdef HAVE_MPI if ( 1 < parallel_size() ) { assert( sizeof(char) == 1 ); char * const recv_buf = new char[ length ]; std::memset( recv_buf , 0 , length ); const int success = MPI_Allreduce( buffer , recv_buf , length , MPI_BYTE , MPI_BOR , communicator_); if ( MPI_SUCCESS != success ) { std::ostringstream errmsg; errmsg << "Ioss::ParallelUtils::attribute_reduction - MPI_Allreduce failed"; IOSS_ERROR(errmsg); } std::memcpy( buffer , recv_buf , length ); delete[] recv_buf ; } #endif }
void DatabaseIO::create_path(const std::string &filename) const { bool error_found = false; std::ostringstream errmsg; if (myProcessor == 0) { Ioss::FileInfo file = Ioss::FileInfo(filename); std::string path = file.pathname(); const int mode = 0777; // Users umask will be applied to this. auto iter = path.begin(); while (iter != path.end() && !error_found) { iter = std::find(iter, path.end(), '/'); std::string path_root = std::string(path.begin(), iter); if (iter != path.end()) { ++iter; // Skip past the '/' } if (path_root.empty()) { // Path started with '/' continue; } struct stat st; if (stat(path_root.c_str(), &st) != 0) { if (mkdir(path_root.c_str(), mode) != 0 && errno != EEXIST) { errmsg << "ERROR: Cannot create directory '" << path_root << "' : " << std::strerror(errno) << "\n"; error_found = true; } } else if (!S_ISDIR(st.st_mode)) { errno = ENOTDIR; errmsg << "ERROR: Path '" << path_root << "' is not a directory.\n"; error_found = true; } } } else { // Give the other processors something to say in case there is an error. errmsg << "ERROR: Could not create path. See processor 0 output for more " "details.\n"; } // Sync all processors with error status... // All processors but 0 will have error_found=false // Processor 0 will have error_found = true or false depending on path // result. int is_error = error_found ? 1 : 0; error_found = (util().global_minmax(is_error, Ioss::ParallelUtils::DO_MAX) == 1); if (error_found) { IOSS_ERROR(errmsg); } }
Ioss::Property Ioss::PropertyManager::get(const std::string& property_name) const { PropMapType::const_iterator iter = properties.find(property_name); if (iter == properties.end()) { std::ostringstream errmsg; errmsg << "ERROR: Could not find property '" << property_name << "'\n"; IOSS_ERROR(errmsg); } return (*iter).second; }
Ioss::Transform* Factory::create(const std::string& type) { Ioss::Transform *transform = NULL; FactoryMap::iterator iter = registry()->find(type); if (iter == registry()->end()) { if (registry()->size() == 0) { std::ostringstream errmsg; errmsg << "FATAL: No transformations have been registered.\n" << " Was Iotr::Initializer::initialize() called?\n\n"; IOSS_ERROR(errmsg); } else { std::ostringstream errmsg; errmsg << "FATAL: The transform named '" << type << "' is not supported.\n"; IOSS_ERROR(errmsg); } } else { Factory* factory = (*iter).second; transform = factory->make(type); } return transform; }
void Ioss::Map::build_reverse_map(int64_t num_to_get, int64_t offset) { // Stored as a sorted vector of <global_id, local_id> pairs... // To build incrementally: // 0. PRE: reverseElementMap is sorted, size >= 0. // 1. Build vector of current ids. -- new_ids // 2. Sort that vector. // 3. Copy reverseElementMap to old_ids, empty reverseElementMap. // 4. Merge old_ids and new_ids to reverseElementMap. // 5. Check for duplicate global_ids... // Build a vector containing the current ids... ReverseMapContainer new_ids(num_to_get); for (int64_t i=0; i < num_to_get; i++) { int64_t local_id = offset + i + 1; new_ids[i] = std::make_pair(map[local_id], local_id); if (map[local_id] <= 0) { std::ostringstream errmsg; errmsg << "\nERROR: " << entityType << " map detected non-positive global id " << map[local_id] << " for " << entityType << " with local id " << local_id << " on processor " << myProcessor << ".\n"; IOSS_ERROR(errmsg); } } // Sort that vector... std::sort(new_ids.begin(), new_ids.end(), IdPairCompare()); int64_t new_id_min = new_ids.empty() ? 0 : new_ids.front().first; int64_t old_id_max = reverse.empty() ? 0 : reverse.back().first; if (new_id_min > old_id_max) { reverse.insert(reverse.end(), new_ids.begin(), new_ids.end()); } else { // Copy reverseElementMap to old_ids, empty reverseElementMap. ReverseMapContainer old_ids; old_ids.swap(reverse); assert(reverse.empty()); // Merge old_ids and new_ids to reverseElementMap. reverse.reserve(old_ids.size() + new_ids.size()); std::merge(old_ids.begin(), old_ids.end(), new_ids.begin(), new_ids.end(), std::inserter(reverse, reverse.begin()), IdPairCompare()); } // Check for duplicate ids... #ifndef NDEBUG verify_no_duplicate_ids(reverse); #endif }
void Ioss::Map::set_map(INT *ids, size_t count, size_t offset) { for (size_t i=0; i < count; i++) { ssize_t local_id = offset + i + 1; map[local_id] = ids[i]; if (local_id != ids[i]) { map[0] = 1; } if (ids[i] <= 0) { std::ostringstream errmsg; errmsg << "\nERROR: " << entityType << " mapping routines detected non-positive global id " << ids[i] << " for local id " << local_id << ".\n"; IOSS_ERROR(errmsg); } } }
void Ioss::Map::verify_no_duplicate_ids(std::vector<Ioss::IdPair> &reverse_map) { // Check for duplicate ids... auto dup = std::adjacent_find(reverse_map.begin(), reverse_map.end(), IdPairEqual()); if (dup != reverse_map.end()) { auto other = dup+1; std::ostringstream errmsg; errmsg << "\nERROR: Duplicate " << entityType << " global id detected on processor " << myProcessor << ", filename '" << filename << "'.\n" << " Global id " << (*dup).first << " assigned to local " << entityType << "s " << (*dup).second << " and " << (*other).second << ".\n"; IOSS_ERROR(errmsg); } }
Ioss::ElementTopology* Ioss::ElementTopology::factory(const std::string& type, bool ok_to_fail) { std::string ltype = Ioss::Utils::lowercase(type); Ioss::ElementTopology* inst = nullptr; Ioss::ElementTopologyMap::iterator iter = registry().find(ltype); if (iter == registry().end()) { std::string base1 = "super"; if (ltype.find(base1) == 0) { // A super element can have a varying number of nodes. Create // an IO element type for this super element. The node count // should be encoded in the 'type' as 'super42' for a 42-node // superelement. Ioss::Super::make_super(ltype); iter = registry().find(ltype); } else { // See if 'type' contains a '-'. Some codes create their // own topologies by adding a "-something" onto the end of a // standard topology. size_t dash = ltype.find('-'); if (dash != std::string::npos) { std::string sub_type = ltype.substr(0, dash); iter = registry().find(sub_type); } } } if (iter == registry().end()) { if (!ok_to_fail) { std::ostringstream errmsg; errmsg << "ERROR: The topology type '" << type << "' is not supported."; IOSS_ERROR(errmsg); } } else { inst = (*iter).second; } return inst; }
int64_t Ioss::Map::global_to_local(int64_t global, bool must_exist) const { int64_t local = global; if (map[0] == 1) { RMapI iter = std::lower_bound(reverse.begin(), reverse.end(), global, IdPairCompare()); if (iter != reverse.end() && iter->first == global) local = iter->second; else local = 0; } else if (!must_exist && global > (int64_t)map.size()-1) { local = 0; } if (local > (int64_t)map.size()-1 || (local <= 0 && must_exist)) { std::ostringstream errmsg; errmsg << "ERROR: Ioss Mapping routines detected " << entityType << " with global id equal to " << global << " returns a local id of " << local << " which is invalid. This should not happen, please report.\n"; IOSS_ERROR(errmsg); } return local; }
void Ioss::ParallelUtils::gather(int64_t my_value, std::vector<int64_t> &result) const { if (parallel_rank() == 0) { result.resize(parallel_size()); } #ifdef HAVE_MPI if (parallel_size() > 1) { const int success = MPI_Gather((void*)&my_value, 1, MPI_LONG_LONG_INT, (void*)&result[0], 1, MPI_LONG_LONG_INT, 0, communicator_); if (success != MPI_SUCCESS) { std::ostringstream errmsg; errmsg << "Ioss::ParallelUtils::gather - MPI_Gather failed"; IOSS_ERROR(errmsg); } } else { result[0] = my_value; } #else result[0] = my_value; #endif }
void Ioss::ParallelUtils::gather(std::vector<int64_t> &my_values, std::vector<int64_t> &result) const { size_t count = my_values.size(); if (parallel_rank() == 0) { result.resize(count * parallel_size()); } #ifdef HAVE_MPI if (parallel_size() > 1) { const int success = MPI_Gather((void*)TOPTR(my_values), count, MPI_LONG_LONG_INT, (void*)TOPTR(result), count, MPI_LONG_LONG_INT, 0, communicator_); if (success != MPI_SUCCESS) { std::ostringstream errmsg; errmsg << "Ioss::ParallelUtils::gather - MPI_Gather failed"; IOSS_ERROR(errmsg); } } else { std::copy(my_values.begin(), my_values.end(), result.begin()); } #else std::copy(my_values.begin(), my_values.end(), result.begin()); #endif }
void DatabaseIO::initialize(const Ioss::Region * /*region*/) const { if (!initialized_) { assert(layout_ == nullptr); assert(legend_ == nullptr); DatabaseIO *new_this = const_cast<DatabaseIO *>(this); if (properties.exists("FIELD_SEPARATOR")) { new_this->separator_ = properties.get("FIELD_SEPARATOR").get_string(); } if (properties.exists("FILE_FORMAT")) { std::string format = properties.get("FILE_FORMAT").get_string(); if (Ioss::Utils::case_strcmp(format, "spyhis") == 0) { new_this->fileFormat = SPYHIS; } } bool append = open_create_behavior() == Ioss::DB_APPEND; // Try to open file... new_this->logStream = nullptr; if (util().parallel_rank() == 0) { new_this->logStream = open_stream(get_filename(), &(new_this->streamNeedsDelete), append); if (new_this->logStream == nullptr) { std::ostringstream errmsg; errmsg << "ERROR: Could not create heartbeat file '" << get_filename() << "'\n"; IOSS_ERROR(errmsg); } } // Pull variables from the regions property data... if (properties.exists("TIME_STAMP_FORMAT")) { new_this->tsFormat = properties.get("TIME_STAMP_FORMAT").get_string(); } if (properties.exists("SHOW_TIME_STAMP")) { bool show_time_stamp = properties.get("SHOW_TIME_STAMP").get_int() == 1; if (!show_time_stamp) { new_this->tsFormat = ""; } } if (properties.exists("PRECISION")) { new_this->precision_ = properties.get("PRECISION").get_int(); } if (properties.exists("FIELD_WIDTH")) { new_this->fieldWidth_ = properties.get("FIELD_WIDTH").get_int(); } else { // +1.xxxxxxe+00 The x count is the precision the "+1.e+00" is the 7 new_this->fieldWidth_ = precision_ + 7; } if (properties.exists("SHOW_LABELS")) { new_this->showLabels = (properties.get("SHOW_LABELS").get_int() == 1); } if (properties.exists("SHOW_LEGEND")) { new_this->showLegend = (properties.get("SHOW_LEGEND").get_int() == 1 && !new_this->appendOutput); } if (properties.exists("SHOW_TIME_FIELD")) { new_this->addTimeField = (properties.get("SHOW_TIME_FIELD").get_int() == 1); } if (fileFormat == SPYHIS) { new_this->addTimeField = true; new_this->showLegend = true; new_this->showLabels = false; new_this->tsFormat = ""; } if (showLegend) { new_this->legend_ = new Layout(false, precision_, separator_, fieldWidth_); if (!tsFormat.empty()) { new_this->legend_->add_literal("+"); new_this->legend_->add_literal(time_stamp(tsFormat)); new_this->legend_->add_literal(" "); } if (addTimeField) { if (fileFormat == SPYHIS) { new_this->legend_->add_legend("TIME"); } else { new_this->legend_->add_legend("Time"); } } } new_this->initialized_ = true; } }
DatabaseIO::DatabaseIO(Region *region, std::string filename, DatabaseUsage db_usage, MPI_Comm communicator, const PropertyManager &props) : properties(props), commonSideTopology(nullptr), DBFilename(std::move(filename)), dbState(STATE_INVALID), isParallel(false), myProcessor(0), cycleCount(0), overlayCount(0), timeScaleFactor(1.0), splitType(SPLIT_BY_TOPOLOGIES), dbUsage(db_usage), dbIntSizeAPI(USE_INT32_API), lowerCaseVariableNames(true), util_(communicator), region_(region), isInput(is_input_event(db_usage)), isParallelConsistent(true), singleProcOnly(db_usage == WRITE_HISTORY || db_usage == WRITE_HEARTBEAT || SerializeIO::isEnabled()), doLogging(false), useGenericCanonicalName(false) { isParallel = util_.parallel_size() > 1; myProcessor = util_.parallel_rank(); // Check environment variable IOSS_PROPERTIES. If it exists, parse // the contents and add to the 'properties' map. std::string env_props; if (util_.get_environment("IOSS_PROPERTIES", env_props, isParallel)) { // env_props string should be of the form // "PROP1=VALUE1:PROP2=VALUE2:..." std::vector<std::string> prop_val = tokenize(env_props, ":"); for (auto &elem : prop_val) { std::vector<std::string> property = tokenize(elem, "="); if (property.size() != 2) { std::ostringstream errmsg; errmsg << "ERROR: Invalid property specification found in " "IOSS_PROPERTIES environment variable\n" << " Found '" << elem << "' which is not of the correct PROPERTY=VALUE form"; IOSS_ERROR(errmsg); } std::string prop = Utils::uppercase(property[0]); std::string value = property[1]; std::string up_value = Utils::uppercase(value); bool all_digit = value.find_first_not_of("0123456789") == std::string::npos; if (myProcessor == 0) { std::cerr << "IOSS: Adding property '" << prop << "' with value '" << value << "'\n"; } if (all_digit) { int int_value = std::strtol(value.c_str(), nullptr, 10); properties.add(Property(prop, int_value)); } else if (up_value == "TRUE" || up_value == "YES") { properties.add(Property(prop, 1)); } else if (up_value == "FALSE" || up_value == "NO") { properties.add(Property(prop, 0)); } else { properties.add(Property(prop, value)); } } } if (properties.exists("INTEGER_SIZE_API")) { int isize = properties.get("INTEGER_SIZE_API").get_int(); if (isize == 8) { set_int_byte_size_api(Ioss::USE_INT64_API); } } { bool logging; if (Utils::check_set_bool_property(properties, "LOGGING", logging)) { set_logging(logging); } } Utils::check_set_bool_property(properties, "LOWER_CASE_VARIABLE_NAMES", lowerCaseVariableNames); Utils::check_set_bool_property(properties, "USE_GENERIC_CANONICAL_NAMES", useGenericCanonicalName); { bool consistent; if (Utils::check_set_bool_property(properties, "PARALLEL_CONSISTENCY", consistent)) { set_parallel_consistency(consistent); } } if (!is_input()) { // Create full path to the output file at this point if it doesn't // exist... create_path(DBFilename); } }
int64_t DatabaseIO::put_field_internal(const Ioss::Region* region, const Ioss::Field& field, void *data, size_t data_size) const { initialize(region); Ioss::Field::RoleType role = field.get_role(); int64_t num_to_get = field.verify(data_size); if ((role == Ioss::Field::TRANSIENT || role == Ioss::Field::REDUCTION) && num_to_get == 1) { int ncomp = field.transformed_storage()->component_count(); if (legend_ != NULL && layout_ != NULL) { if (ncomp == 1) { legend_->add_legend(field.get_name()); } else { const Ioss::VariableType *var_type = field.transformed_storage(); for (int i=0; i < ncomp; i++) { std::string var_name = var_type->label_name(field.get_name(), i+1, '_'); legend_->add_legend(var_name); } } } if (field.get_type() == Ioss::Field::STRING) { // Assume that if layout_ is NULL, then we want special one-line output. if (layout_ == NULL) { Layout layout(false, 0, separator_, fieldWidth_); layout.add_literal("-"); layout.add_literal(time_stamp(tsFormat)); layout.add_literal(" "); layout.add_literal(*(std::string*)data); if (logStream != NULL) *logStream << layout << std::endl; } else { layout_->add(field.get_name(), *(std::string*)data); } } else { if (layout_ == NULL) { std::ostringstream errmsg; errmsg << "INTERNAL ERROR: Unexpected NULL layout.\n"; IOSS_ERROR(errmsg); } if (field.get_type() == Ioss::Field::INTEGER) { assert(field.transformed_count() == 1); int *i_data = (int*)data; std::vector<int> idata(ncomp); for (int i=0; i < ncomp; i++) { idata[i] = i_data[i]; } layout_->add(field.get_name(), idata); } else { std::vector<double> rdata(ncomp); double *r_data = (double*)data; for (int i=0; i < ncomp; i++) { rdata[i] = r_data[i]; } layout_->add(field.get_name(), rdata); } } } else { std::ostringstream errmsg; errmsg << "ERROR: Can not handle non-TRANSIENT or non-REDUCTION fields on regions.\n"; IOSS_ERROR(errmsg); } return num_to_get; }
Ioex::SuperElement::SuperElement(std::string filename, const std::string &my_name) : Ioss::GroupingEntity(nullptr, my_name, 1), fileName(std::move(filename)), numDOF(0), num_nodes(0), numEIG(0), num_dim(0), filePtr(-1) { // For now, we will open the raw netcdf file here and parse the // dimensions. This is probably not how this should be done long // term, but is better than putting netcdf calls in application... // Check that file specified by filename exists... // Add working directory if needed. std::string local_filename = fileName; int status = nc_open(local_filename.c_str(), NC_NOWRITE, &filePtr); if (status != NC_NOERR) { std::ostringstream errmsg; errmsg << "ERROR: Failed to open superelement file '" << local_filename << "'."; IOSS_ERROR(errmsg); } // At this point have a valid netcdf file handle. // Read some dimensions to determine size of Mass and Stiffness // matrix. nc_get_dimension(filePtr, "NumDof", "number of degrees of freedom", &numDOF); nc_get_dimension(filePtr, "num_nodes", "number of nodes", &num_nodes); nc_get_dimension(filePtr, "NumEig", "number of eigenvalues", &numEIG); nc_get_dimension(filePtr, "num_dim", "number of dimensions", &num_dim); size_t num_constraints = 0; nc_get_dimension(filePtr, "NumConstraints", "number of interface dof", &num_constraints); assert(num_constraints == numDOF - numEIG); // Add the standard properties... properties.add(Ioss::Property(this, "numDOF", Ioss::Property::INTEGER)); if (num_nodes > 0) { properties.add(Ioss::Property(this, "num_nodes", Ioss::Property::INTEGER)); } properties.add(Ioss::Property(this, "numEIG", Ioss::Property::INTEGER)); properties.add(Ioss::Property(this, "numDIM", Ioss::Property::INTEGER)); properties.add(Ioss::Property(this, "numConstraints", Ioss::Property::INTEGER)); // Add the standard fields... if (num_nodes > 0) { fields.add(Ioss::Field("coordx", Ioss::Field::REAL, SCALAR(), Ioss::Field::MESH, num_nodes)); fields.add(Ioss::Field("coordy", Ioss::Field::REAL, SCALAR(), Ioss::Field::MESH, num_nodes)); fields.add(Ioss::Field("coordz", Ioss::Field::REAL, SCALAR(), Ioss::Field::MESH, num_nodes)); fields.add( Ioss::Field("node_num_map", Ioss::Field::REAL, SCALAR(), Ioss::Field::MESH, num_nodes)); fields.add(Ioss::Field("cbmap", Ioss::Field::REAL, SCALAR(), Ioss::Field::MESH, 2 * num_nodes * num_dim)); } fields.add(Ioss::Field("Kr", Ioss::Field::REAL, SCALAR(), Ioss::Field::MESH, numDOF * numDOF)); fields.add(Ioss::Field("Mr", Ioss::Field::REAL, SCALAR(), Ioss::Field::MESH, numDOF * numDOF)); // There are additional properties and fields on the netcdf file, // but for now we only need "Kr" and "Mr" }
int64_t Ioex::SuperElement::internal_get_field_data(const Ioss::Field &field, void *data, size_t data_size) const { size_t num_to_get = field.verify(data_size); if (field.get_name() == "cbmap") { assert(num_to_get == 2 * num_nodes * num_dim); int status = nc_get_array(filePtr, "cbmap", reinterpret_cast<double *>(data)); if (status != 0) { std::ostringstream errmsg; errmsg << "ERROR: Could not load coodintate data field 'cbmap' from file '" << fileName << "'."; IOSS_ERROR(errmsg); } } else if (field.get_name() == "node_num_map") { assert(num_to_get == num_nodes); int status = nc_get_array(filePtr, "node_num_map", reinterpret_cast<double *>(data)); if (status != 0) { std::ostringstream errmsg; errmsg << "ERROR: Could not load coodintate data field 'node_num_map' from file '" << fileName << "'."; IOSS_ERROR(errmsg); } } else if (field.get_name() == "coordx") { assert(num_to_get == num_nodes); int status = nc_get_array(filePtr, "coordx", reinterpret_cast<double *>(data)); if (status != 0) { std::ostringstream errmsg; errmsg << "ERROR: Could not load coodintate data field 'coordx' from file '" << fileName << "'."; IOSS_ERROR(errmsg); } } else if (field.get_name() == "coordy") { assert(num_to_get == num_nodes); int status = nc_get_array(filePtr, "coordy", reinterpret_cast<double *>(data)); if (status != 0) { std::ostringstream errmsg; errmsg << "ERROR: Could not load coodintate data field 'coordy' from file '" << fileName << "'."; IOSS_ERROR(errmsg); } } else if (field.get_name() == "coordz") { assert(num_to_get == num_nodes); int status = nc_get_array(filePtr, "coordz", reinterpret_cast<double *>(data)); if (status != 0) { std::ostringstream errmsg; errmsg << "ERROR: Could not load coodintate data field 'coordz' from file '" << fileName << "'."; IOSS_ERROR(errmsg); } } else if (field.get_name() == "Kr") { assert(num_to_get == numDOF * numDOF); int status = nc_get_array(filePtr, "Kr", reinterpret_cast<double *>(data)); if (status != 0) { std::ostringstream errmsg; errmsg << "ERROR: Could not load stiffness matrix field 'Kr' from file '" << fileName << "'."; IOSS_ERROR(errmsg); } } else if (field.get_name() == "Mr") { assert(num_to_get == numDOF * numDOF); int status = nc_get_array(filePtr, "Mr", reinterpret_cast<double *>(data)); if (status != 0) { std::ostringstream errmsg; errmsg << "ERROR: Could not load mass matrix field 'Mr' from file '" << fileName << "'."; IOSS_ERROR(errmsg); } } else { std::cerr << "WARNING: " << type() << " '" << name() << "'. Unknown input field '" << field.get_name() << "'"; return -4; } return num_to_get; }