Example #1
0
void build_local_element_map(RegionVector &part_mesh,
			     std::vector<INT> &local_element_map)
{
  size_t global = 0;
  size_t offset = 0;
  for (size_t p = 0; p < part_mesh.size(); p++) {

    Ioss::ElementBlockContainer ebs = part_mesh[p]->get_element_blocks();
    Ioss::ElementBlockContainer::const_iterator i = ebs.begin();

    while (i != ebs.end()) {
      Ioss::ElementBlock *eb = *i++; 
      size_t num_elem  = eb->get_property("entity_count").get_int();
      if (entity_is_omitted(eb)) {
	// Fill local_element_map with -1 for the omitted elements.
	for (size_t j = 0; j < num_elem; j++) {
	  local_element_map[offset+j] = -1;
	}
      } else {
	for (size_t j = 0; j < num_elem; j++) {
	  local_element_map[offset+j] = global++;
	}
      }
      offset += num_elem;
    }
  }
}
Example #2
0
Block::Block(const Ioss::ElementBlock &other)
{
  id                  = other.get_property("id").get_int();
  elementCount        = other.get_property("entity_count").get_int();
  nodesPerElement     = other.get_property("topology_node_count").get_int();
  attributeCount      = other.get_property("attribute_count").get_int();
  offset_             = other.get_offset();
  std::string el_type = other.get_property("topology_type").get_string();
  if (other.property_exists("original_topology_type")) {
    el_type = other.get_property("original_topology_type").get_string();
  }

  std::strncpy(elType, el_type.c_str(), MAX_STR_LENGTH);
  elType[MAX_STR_LENGTH] = 0;

  // Fixup an exodusII kludge.  For triangular elements, the same
  // name is used for 2D elements and 3D shell elements.  Convert
  // to unambiguous names for the IO Subsystem.  The 2D name
  // stays the same, the 3D name becomes 'trishell#'
  // Here, we need to map back to the 'triangle' name...
  if (std::strncmp(elType, "trishell", 8) == 0)
    std::strncpy(elType, "triangle", 8);

  std::string io_name = other.name();
  std::strncpy(name, io_name.c_str(), MAX_STR_LENGTH);
  name[MAX_STR_LENGTH] = 0;
}
// ========================================================================
void process_elementblocks(Ioss::Region &region, stk::mesh::BulkData &bulk)
{
    const Ioss::ElementBlockContainer& elem_blocks = region.get_element_blocks();

    for(Ioss::ElementBlockContainer::const_iterator it = elem_blocks.begin();
            it != elem_blocks.end(); ++it) {
        Ioss::ElementBlock *entity = *it;

        if (stk::io::include_entity(entity)) {
            const std::string &name = entity->name();
            const stk::mesh::MetaData& meta = stk::mesh::MetaData::get(bulk);
            stk::mesh::Part* const part = meta.get_part(name);
            STKIORequire(part != NULL);

            const stk::topology topo = part->topology();
            if (topo == stk::topology::INVALID_TOPOLOGY) {
                std::ostringstream msg ;
                msg << " INTERNAL_ERROR: Part " << part->name() << " returned INVALID from get_topology()";
                throw std::runtime_error( msg.str() );
            }

            std::vector<int> elem_ids ;
            std::vector<int> connectivity ;

            entity->get_field_data("ids", elem_ids);
            entity->get_field_data("connectivity", connectivity);

            size_t element_count = elem_ids.size();
            int nodes_per_elem = topo.num_nodes();

            stk::mesh::EntityIdVector connectivity2(nodes_per_elem);

            std::vector<int>::const_iterator connBegin = connectivity.begin();
            std::vector<stk::mesh::Entity> elements(element_count);
            for(size_t i=0; i<element_count; ++i, connBegin += nodes_per_elem) {
                std::copy(connBegin, connBegin + nodes_per_elem, connectivity2.begin());
                elements[i] = stk::mesh::declare_element(bulk, *part, elem_ids[i], connectivity2);
            }

            // For this example, we are just taking all attribute fields
            // found on the io database and populating fields on the
            // corresponding mesh part.  In practice, would probably be
            // selective about which attributes to use...
            Ioss::NameList names;
            entity->field_describe(Ioss::Field::ATTRIBUTE, &names);
            for (Ioss::NameList::const_iterator I = names.begin(); I != names.end(); ++I) {
                if (*I == "attribute" && names.size() > 1)
                    continue;
                stk::mesh::FieldBase *field = meta.get_field<stk::mesh::FieldBase>(stk::topology::ELEMENT_RANK, *I);
                stk::io::field_data_from_ioss(bulk, field, elements, entity, *I);

            }
        }
    }
}
Example #4
0
  AxisAlignedBoundingBox DatabaseIO::get_bounding_box(const Ioss::ElementBlock *eb) const
  {
    if (elementBlockBoundingBoxes.empty()) {
      // Calculate the bounding boxes for all element blocks...
      std::vector<double> coordinates;
      Ioss::NodeBlock *   nb = get_region()->get_node_blocks()[0];
      nb->get_field_data("mesh_model_coordinates", coordinates);
      ssize_t nnode = nb->get_property("entity_count").get_int();
      ssize_t ndim  = nb->get_property("component_degree").get_int();

      Ioss::ElementBlockContainer element_blocks = get_region()->get_element_blocks();
      size_t                      nblock         = element_blocks.size();
      std::vector<double>         minmax;
      minmax.reserve(6 * nblock);

      for (auto &block : element_blocks) {
        double xmin, ymin, zmin, xmax, ymax, zmax;
        if (block->get_database()->int_byte_size_api() == 8) {
          std::vector<int64_t> connectivity;
          block->get_field_data("connectivity_raw", connectivity);
          calc_bounding_box(ndim, nnode, coordinates, connectivity, xmin, ymin, zmin, xmax, ymax,
                            zmax);
        }
        else {
          std::vector<int> connectivity;
          block->get_field_data("connectivity_raw", connectivity);
          calc_bounding_box(ndim, nnode, coordinates, connectivity, xmin, ymin, zmin, xmax, ymax,
                            zmax);
        }

        minmax.push_back(xmin);
        minmax.push_back(ymin);
        minmax.push_back(zmin);
        minmax.push_back(-xmax);
        minmax.push_back(-ymax);
        minmax.push_back(-zmax);
      }

      util().global_array_minmax(minmax, Ioss::ParallelUtils::DO_MIN);

      for (size_t i = 0; i < element_blocks.size(); i++) {
        Ioss::ElementBlock *   block = element_blocks[i];
        const std::string &    name  = block->name();
        AxisAlignedBoundingBox bbox(minmax[6 * i + 0], minmax[6 * i + 1], minmax[6 * i + 2],
                                    -minmax[6 * i + 3], -minmax[6 * i + 4], -minmax[6 * i + 5]);
        elementBlockBoundingBoxes[name] = bbox;
      }
    }
    return elementBlockBoundingBoxes[eb->name()];
  }
// ========================================================================
void process_elementblocks(Ioss::Region &region, stk::mesh::MetaData &meta)
{
    const stk::mesh::EntityRank element_rank = stk::topology::ELEMENT_RANK;

    const Ioss::ElementBlockContainer& elem_blocks = region.get_element_blocks();
    stk::io::default_part_processing(elem_blocks, meta, element_rank);

    // Parts were created above, now handle element block specific
    // information (topology, attributes, ...);
    for(Ioss::ElementBlockContainer::const_iterator it = elem_blocks.begin();
            it != elem_blocks.end(); ++it) {
        Ioss::ElementBlock *entity = *it;

        if (stk::io::include_entity(entity)) {
            stk::mesh::Part* const part = meta.get_part(entity->name());
            STKIORequire(part != NULL);

            const stk::mesh::EntityRank part_rank = part->primary_entity_rank();

            // Element Block attributes (if any)...
            /** \todo IMPLEMENT truly handle attribute fields... For this
             * case we are just defining a field for each attribute field
             * that is present in the mesh...
             */
            stk::io::define_io_fields(entity, Ioss::Field::ATTRIBUTE,
                                      *part,
                                      part_rank);

            /** \todo IMPLEMENT truly handle fields... For this case we
             * are just defining a field for each transient field that is
             * present in the mesh...
             */
            stk::io::define_io_fields(entity, Ioss::Field::TRANSIENT,
                                      *part,
                                      part_rank);
        }
    }
}
Example #6
0
void generate_element_ids(RegionVector &part_mesh,
			  const std::vector<INT> &local_element_map,
			  std::vector<INT> &global_element_map)
{
  // Follow same logic as 'build_local_element_map' to ensure elements
  // are processed in same order.

  // Many models do not use the element number map at all, so they
  // will have a 1..numel map.  If all parts have that, then we don't
  // want to do any fancy duplicate removal and other processing, just
  // output a 1..numel map for the output mesh...  We still generate
  // the global_element_map, but check whether any of the part blocks
  // have a non-1..numel map...
  bool has_map = false;
  size_t offset = 0;
  for (size_t p = 0; p < part_mesh.size(); p++) {
    Ioss::ElementBlockContainer ebs = part_mesh[p]->get_element_blocks();
    Ioss::ElementBlockContainer::const_iterator i = ebs.begin();

    while (i != ebs.end()) {
      Ioss::ElementBlock *eb = *i++; 
      INT num_elem  = eb->get_property("entity_count").get_int();
      if (!entity_is_omitted(eb)) {
	std::vector<INT> part_ids;
	eb->get_field_data("ids", part_ids);

	if (!has_map) { 
	  INT eb_offset = eb->get_offset();
	  for (INT j = 0; j < num_elem; j++) {
	    if (part_ids[j] != eb_offset+j+1) {
	      has_map = true;
	      break;
	    }
	  }
	}

	for (INT j = 0; j < num_elem; j++) {
	  INT gpos = local_element_map[offset+j];
	  if (gpos >= 0)
	    global_element_map[gpos] = part_ids[j];
	}
      }
      offset += num_elem;
    }
  }
  // Check for duplicates...
  // NOTE: Used to use an indexed sort here, but if there was a
  // duplicate id, it didnt really care whether part 1 or part N's
  // index came first which causes really screwy element maps.
  // Instead, lets sort a vector containing pairs of <id, index> where
  // the index will always? increase for increasing part numbers...
  std::vector<std::pair<INT,INT> > index(global_element_map.size());
  for (size_t i=0; i < index.size(); i++) {
    index[i] = std::make_pair(global_element_map[i],(INT)i);
  }

  std::sort(index.begin(), index.end());

  INT max_id = index[index.size()-1].first + 1;
  
  size_t beg = 0;
  for (size_t i=1; i < index.size(); i++) {
    if (index[beg].first == index[i].first) {
      // Duplicate found... Assign it a new id greater than any
      // existing id...  (What happens if we exceed INT_MAX?)
      global_element_map[index[i].second] = max_id++;
      // Keep 'beg' the same in case multiple duplicate of this value.
    } else {
      beg = i;
    }
  }
}
/// This function shows the basic calls needed to perform definition
/// and input of the mesh model and definition and periodic output
/// of a results database. The function is given the mesh filename
/// and the output filename and goes through all steps of
/// associating the filename with an Ioss::DatabaseIO object of the
/// correct type ("exodusII" in this example); creating an
/// Ioss::Region and then defining an stk::mesh corresponding to
/// this mesh.  The function also provides an example of how
/// specific element blocks existing in the mesh database could be
/// omitted from the analysis model.
///
/// The example then shows how to define a results database
/// corresponding to the analysis model and periodically output the
/// results in an execute loop.
///
/// A true application would have to provide additional
/// functionality and robustness, but the example shows how the
/// basic functionality can be provided by an application.
///
/// Note that the paradigm illustrated here is different than the
/// mesh input and output paradigm provided in the current
/// framework.  In this case, the application is responsible for the
/// majority of the IO behavior and the toolkit only provides some
/// helper functions to bridge between the Ioss and the stk::mesh.
/// It is hoped that this paradigm will result in more functionality
/// for the application with less complication and overhead.
void io_example( const std::string& in_filename,
                 const std::string& out_filename,
                 const std::string& decomp_method)
{
    // Initialize IO system.  Registers all element types and storage
    // types and the exodusII default database type.
    Ioss::Init::Initializer init_db;

    std::cout << "========================================================================\n"
              << " Copy input mesh to output mesh.                                        \n"
              << "========================================================================\n";

    std::string dbtype("exodusII");
    Ioss::PropertyManager properties;
    if (!decomp_method.empty()) {
        properties.add(Ioss::Property("DECOMPOSITION_METHOD", Ioss::Utils::uppercase(decomp_method)));
    }
    Ioss::DatabaseIO *dbi = Ioss::IOFactory::create(dbtype, in_filename, Ioss::READ_MODEL,
                            MPI_COMM_WORLD, properties);
    if (dbi == NULL || !dbi->ok()) {
        std::cerr  << "ERROR: Could not open database '" << in_filename
                   << "' of type '" << dbtype << "'\n";
        std::exit(EXIT_FAILURE);
    }

    std::cout << "Reading input file:   " << in_filename << "\n";
    // NOTE: 'in_region' owns 'dbi' pointer at this time...
    Ioss::Region in_region(dbi, "input_model");

    // SUBSETTING PARSING/PREPROCESSING...
    // Just an example of how application could control whether an
    // entity is subsetted or not...


#if 0
    // Example command line in current code corresponding to behavior below:
    std::cout << "\nWhen processing file multi-block.g for use case 2, the blocks below will be omitted:\n";
    std::cout << "\tOMIT BLOCK Cblock Eblock I1 I2\n\n";
    Ioss::ElementBlock *eb = in_region.get_element_block("cblock");
    if (eb != NULL)
        eb->property_add(Ioss::Property(std::string("omitted"), 1));

    eb = in_region.get_element_block("eblock");
    if (eb != NULL)
        eb->property_add(Ioss::Property(std::string("omitted"), 1));

    eb = in_region.get_element_block("i1");
    if (eb != NULL)
        eb->property_add(Ioss::Property(std::string("omitted"), 1));

    eb = in_region.get_element_block("i2");
    if (eb != NULL)
        eb->property_add(Ioss::Property(std::string("omitted"), 1));
#endif

#if 0
    // Example for subsetting -- omit "odd" blocks
    if (entity->type() == Ioss::ELEMENTBLOCK) {
        int id = entity->get_property("id").get_int();
        if (id % 2) {
            entity->property_add(Ioss::Property(std::string("omitted"), 1));
            std::cout << "Skipping " << entity->type_string() << ": "  << entity->name() << "\n";
        }
    }
#endif

    //----------------------------------
    // Process Entity Types. Subsetting is possible.

    static size_t spatial_dimension = in_region.get_property("spatial_dimension").get_int();

    stk::mesh::MetaData fem_meta_data( spatial_dimension );
    process_elementblocks(in_region, fem_meta_data);
    process_nodeblocks(in_region,    fem_meta_data);
    process_sidesets(in_region,      fem_meta_data);
    process_nodesets(in_region,      fem_meta_data);

    //----------------------------------
    // Done populating meta data, commit and create bulk data
    fem_meta_data.commit();

    //----------------------------------
    // Process Bulkdata for all Entity Types. Subsetting is possible.
    stk::mesh::BulkData bulk_data(fem_meta_data, MPI_COMM_WORLD);

    bulk_data.modification_begin();
    process_elementblocks(in_region, bulk_data);
    process_nodeblocks(in_region,    bulk_data);
    process_sidesets(in_region,      bulk_data);
    process_nodesets(in_region,      bulk_data);
    bulk_data.modification_end();

    //----------------------------------
    // OUTPUT...Create the output "mesh" portion

    std::cout << "Creating output file: " << out_filename << "\n";
    Ioss::DatabaseIO *dbo = Ioss::IOFactory::create(dbtype, out_filename,
                            Ioss::WRITE_RESULTS,
                            MPI_COMM_WORLD);
    if (dbo == NULL || !dbo->ok()) {
        std::cerr << "ERROR: Could not open results database '" << out_filename
                  << "' of type '" << dbtype << "'\n";
        std::exit(EXIT_FAILURE);
    }

#if 0
    {
        // Code to test the remove_io_part_attribute functionality.
        // Hook this up to a command line option at some point to test nightly...
        const stk::mesh::PartVector & all_parts = fem_meta_data.get_parts();
        for ( stk::mesh::PartVector::const_iterator ip = all_parts.begin(); ip != all_parts.end(); ++ip ) {
            stk::mesh::Part * const part = *ip;
            const stk::mesh::EntityRank part_rank = part->primary_entity_rank();

            if (stk::io::is_part_io_part(*part) && part_rank == 2) {
                std::cout << "Removing part attribute from " << part->name() << "\n";
                stk::io::remove_io_part_attribute(*part);
            }
        }
    }
#endif

    // NOTE: 'out_region' owns 'dbo' pointer at this time...
    Ioss::Region out_region(dbo, "results_output");

    stk::io::define_output_db(out_region, bulk_data, &in_region);
    stk::io::write_output_db(out_region,  bulk_data);

    // ------------------------------------------------------------------------
    /** \todo REFACTOR A real app would register a subset of the
     * fields on the mesh database as fields that the app would want
     * read at one or all or specified steps.  In this example, all
     * fields existing on the input mesh database are defined on the
     * parts in the stk::mesh.
     *
     * The real app would also only register a subset of the stk::mesh
     * fields as output fields and would probably have a mapping from
     * the internally used name to some name picked by the user. In
     * this example, all Ioss::Field::TRANSIENT fields defined on the stk::mesh are
     * output to the results database and the internal stk::mesh field
     * name is used as the name on the database....
     */

    out_region.begin_mode(Ioss::STATE_DEFINE_TRANSIENT);

    // Special processing for nodeblock (all nodes in model)...
    stk::io::ioss_add_fields(fem_meta_data.universal_part(), stk::topology::NODE_RANK,
                             out_region.get_node_blocks()[0],
                             Ioss::Field::TRANSIENT);

    const stk::mesh::PartVector & all_parts = fem_meta_data.get_parts();
    for ( stk::mesh::PartVector::const_iterator
            ip = all_parts.begin(); ip != all_parts.end(); ++ip ) {

        stk::mesh::Part * const part = *ip;

        const stk::mesh::EntityRank part_rank = part->primary_entity_rank();

        // Check whether this part should be output to results database.
        if (stk::io::is_part_io_part(*part)) {
            // Get Ioss::GroupingEntity corresponding to this part...
            Ioss::GroupingEntity *entity = out_region.get_entity(part->name());
            if (entity != NULL) {
                if (entity->type() == Ioss::SIDESET) {
                    Ioss::SideSet *sset = dynamic_cast<Ioss::SideSet*>(entity);
                    assert(sset != NULL);
                    int block_count = sset->block_count();
                    for (int i=0; i < block_count; i++) {
                        Ioss::SideBlock *fb = sset->get_block(i);
                        stk::io::ioss_add_fields(*part, part_rank,
                                                 fb, Ioss::Field::TRANSIENT);
                    }
                } else {
                    stk::io::ioss_add_fields(*part, part_rank,
                                             entity, Ioss::Field::TRANSIENT);
                }
            } else {
                /// \todo IMPLEMENT handle error... Possibly an assert since
                /// I think the corresponding entity should always exist...
            }
        }
    }
    out_region.end_mode(Ioss::STATE_DEFINE_TRANSIENT);
    // ------------------------------------------------------------------------

    // Read and Write transient fields...
    out_region.begin_mode(Ioss::STATE_TRANSIENT);
    int timestep_count = in_region.get_property("state_count").get_int();
    for (int step = 1; step <= timestep_count; step++) {
        double time = in_region.get_state_time(step);

        // Read data from the io input mesh database into stk::mesh fields...
        process_input_request(in_region, bulk_data, step);

        // execute()

        // Write data from the stk::mesh fields out to the output database.a
        int out_step = out_region.add_state(time);
        process_output_request(out_region, bulk_data, out_step);
    }
    out_region.end_mode(Ioss::STATE_TRANSIENT);
}