/// 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);
}
Beispiel #2
0
PromotedElementIO::PromotedElementIO(
  const ElementDescription& elem,
  const stk::mesh::MetaData& metaData,
  stk::mesh::BulkData& bulkData,
  const stk::mesh::PartVector& baseParts,
  const std::string& fileName,
  const VectorFieldType& coordField
) : elem_(elem),
    metaData_(metaData),
    bulkData_(bulkData),
    fileName_(fileName),
    coordinates_(coordField),
    nDim_(metaData.spatial_dimension())
{
  Ioss::Init::Initializer init_db;

  Ioss::PropertyManager properties;

  Ioss::Property intSizeAPI("INTEGER_SIZE_API", 8);
  properties.add(intSizeAPI);

  Ioss::Property intSizeDB("INTEGER_SIZE_DB", 8);
  properties.add(intSizeDB);

  databaseIO = Ioss::IOFactory::create(
        "exodus",
        fileName_,
        Ioss::WRITE_RESULTS,
        bulkData_.parallel(),
        properties
  );
  ThrowRequire(databaseIO != nullptr && databaseIO->ok(true));

  output_ = make_unique<Ioss::Region>(databaseIO, "HighOrderOutput"); //sink for databaseIO
  ThrowRequire(output_ != nullptr);

  const stk::mesh::BucketVector& elem_buckets = bulkData_.get_buckets(
    stk::topology::ELEM_RANK, stk::mesh::selectUnion(baseParts));

  size_t numSubElems = num_sub_elements(nDim_, elem_buckets, elem_.polyOrder);
  std::vector<stk::mesh::EntityId> subElemIds;

  bulkData.generate_new_ids(stk::topology::ELEM_RANK,  numSubElems,  subElemIds);
  ThrowRequire(subElemIds.size() == numSubElems);

  superElemParts_ = super_elem_part_vector(baseParts);
  ThrowRequireMsg(part_vector_is_valid_and_nonempty(superElemParts_),
    "Not all element parts have a super-element mirror");

  output_->begin_mode(Ioss::STATE_DEFINE_MODEL);
  write_node_block_definitions(superElemParts_);
  write_elem_block_definitions(superElemParts_);
  write_sideset_definitions(baseParts);
  output_->end_mode(Ioss::STATE_DEFINE_MODEL);

  output_->begin_mode(Ioss::STATE_MODEL);
  write_coordinate_list(superElemParts_);
  write_element_connectivity(superElemParts_, subElemIds);
  write_sideset_connectivity(baseParts);
  output_->end_mode(Ioss::STATE_MODEL);
}