/// 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); }
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); }