|
Sierra Toolkit
Version of the Day
|
00001 /*------------------------------------------------------------------------*/ 00002 /* Copyright 2010, 2011 Sandia Corporation. */ 00003 /* Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive */ 00004 /* license for use of this work by or on behalf of the U.S. Government. */ 00005 /* Export of this program may require a license from the */ 00006 /* United States Government. */ 00007 /*------------------------------------------------------------------------*/ 00008 00009 #include <stk_io/MeshReadWriteUtils.hpp> 00010 00011 #include <stk_mesh/base/BulkData.hpp> 00012 #include <stk_mesh/base/GetEntities.hpp> 00013 #include <stk_mesh/fem/FEMMetaData.hpp> 00014 #include <stk_mesh/fem/FEMHelpers.hpp> 00015 00016 #include <stk_mesh/base/Field.hpp> 00017 #include <stk_mesh/base/FieldData.hpp> 00018 #include <stk_mesh/base/FieldParallel.hpp> 00019 00020 #include <Shards_BasicTopologies.hpp> 00021 00022 #include <stk_io/IossBridge.hpp> 00023 00024 #include <Ioss_SubSystem.h> 00025 00026 #include <stk_util/util/tokenize.hpp> 00027 #include <iostream> 00028 #include <sstream> 00029 #include <cmath> 00030 00031 #include <limits> 00032 #include <assert.h> 00033 00034 namespace { 00035 void process_surface_entity(Ioss::SideSet *sset, stk_classic::mesh::fem::FEMMetaData &fem_meta) 00036 { 00037 assert(sset->type() == Ioss::SIDESET); 00038 const Ioss::SideBlockContainer& blocks = sset->get_side_blocks(); 00039 stk_classic::io::default_part_processing(blocks, fem_meta); 00040 00041 stk_classic::mesh::Part* const ss_part = fem_meta.get_part(sset->name()); 00042 assert(ss_part != NULL); 00043 00044 stk_classic::mesh::Field<double, stk_classic::mesh::ElementNode> *distribution_factors_field = NULL; 00045 bool surface_df_defined = false; // Has the surface df field been defined yet? 00046 00047 size_t block_count = sset->block_count(); 00048 for (size_t i=0; i < block_count; i++) { 00049 Ioss::SideBlock *sb = sset->get_block(i); 00050 if (stk_classic::io::include_entity(sb)) { 00051 stk_classic::mesh::Part * const sb_part = fem_meta.get_part(sb->name()); 00052 assert(sb_part != NULL); 00053 fem_meta.declare_part_subset(*ss_part, *sb_part); 00054 00055 if (sb->field_exists("distribution_factors")) { 00056 if (!surface_df_defined) { 00057 std::string field_name = sset->name() + "_df"; 00058 distribution_factors_field = 00059 &fem_meta.declare_field<stk_classic::mesh::Field<double, stk_classic::mesh::ElementNode> >(field_name); 00060 stk_classic::io::set_field_role(*distribution_factors_field, Ioss::Field::MESH); 00061 stk_classic::io::set_distribution_factor_field(*ss_part, *distribution_factors_field); 00062 surface_df_defined = true; 00063 } 00064 stk_classic::io::set_distribution_factor_field(*sb_part, *distribution_factors_field); 00065 int side_node_count = sb->topology()->number_nodes(); 00066 stk_classic::mesh::put_field(*distribution_factors_field, 00067 stk_classic::io::part_primary_entity_rank(*sb_part), 00068 *sb_part, side_node_count); 00069 } 00070 } 00071 } 00072 } 00073 00074 size_t get_entities(stk_classic::mesh::Part &part, 00075 const stk_classic::mesh::BulkData &bulk, 00076 std::vector<stk_classic::mesh::Entity*> &entities, 00077 const stk_classic::mesh::Selector *anded_selector) 00078 { 00079 stk_classic::mesh::MetaData & meta = stk_classic::mesh::MetaData::get(part); 00080 stk_classic::mesh::EntityRank type = stk_classic::io::part_primary_entity_rank(part); 00081 00082 stk_classic::mesh::Selector own = meta.locally_owned_part(); 00083 stk_classic::mesh::Selector selector = part & own; 00084 if (anded_selector) selector &= *anded_selector; 00085 00086 get_selected_entities(selector, bulk.buckets(type), entities); 00087 return entities.size(); 00088 } 00089 } 00090 00091 // ======================================================================== 00092 template <typename INT> 00093 void process_surface_entity(const Ioss::SideSet* sset, stk_classic::mesh::BulkData & bulk, INT /*dummy*/) 00094 { 00095 assert(sset->type() == Ioss::SIDESET); 00096 00097 const stk_classic::mesh::fem::FEMMetaData &fem_meta = stk_classic::mesh::fem::FEMMetaData::get(bulk); 00098 00099 size_t block_count = sset->block_count(); 00100 for (size_t i=0; i < block_count; i++) { 00101 Ioss::SideBlock *block = sset->get_block(i); 00102 if (stk_classic::io::include_entity(block)) { 00103 std::vector<INT> side_ids ; 00104 std::vector<INT> elem_side ; 00105 00106 stk_classic::mesh::Part * const sb_part = fem_meta.get_part(block->name()); 00107 stk_classic::mesh::EntityRank elem_rank = fem_meta.element_rank(); 00108 00109 block->get_field_data("ids", side_ids); 00110 block->get_field_data("element_side", elem_side); 00111 00112 assert(side_ids.size() * 2 == elem_side.size()); 00113 stk_classic::mesh::PartVector add_parts( 1 , sb_part ); 00114 00115 size_t side_count = side_ids.size(); 00116 std::vector<stk_classic::mesh::Entity*> sides(side_count); 00117 for(size_t is=0; is<side_count; ++is) { 00118 stk_classic::mesh::Entity* const elem = bulk.get_entity(elem_rank, elem_side[is*2]); 00119 00120 // If NULL, then the element was probably assigned to an 00121 // element block that appears in the database, but was 00122 // subsetted out of the analysis mesh. Only process if 00123 // non-null. 00124 if (elem != NULL) { 00125 // Ioss uses 1-based side ordinal, stk_classic::mesh uses 0-based. 00126 int side_ordinal = elem_side[is*2+1] - 1; 00127 00128 stk_classic::mesh::Entity* side_ptr = NULL; 00129 side_ptr = &stk_classic::mesh::fem::declare_element_side(bulk, side_ids[is], *elem, side_ordinal); 00130 stk_classic::mesh::Entity& side = *side_ptr; 00131 00132 bulk.change_entity_parts( side, add_parts ); 00133 sides[is] = &side; 00134 } else { 00135 sides[is] = NULL; 00136 } 00137 } 00138 00139 const stk_classic::mesh::Field<double, stk_classic::mesh::ElementNode> *df_field = 00140 stk_classic::io::get_distribution_factor_field(*sb_part); 00141 if (df_field != NULL) { 00142 stk_classic::io::field_data_from_ioss(df_field, sides, block, "distribution_factors"); 00143 } 00144 00145 // Add all attributes as fields. 00146 // If the only attribute is 'attribute', then add it; otherwise the other attributes are the 00147 // named components of the 'attribute' field, so add them instead. 00148 Ioss::NameList names; 00149 block->field_describe(Ioss::Field::ATTRIBUTE, &names); 00150 for(Ioss::NameList::const_iterator I = names.begin(); I != names.end(); ++I) { 00151 if(*I == "attribute" && names.size() > 1) 00152 continue; 00153 stk_classic::mesh::FieldBase *field = fem_meta.get_field<stk_classic::mesh::FieldBase> (*I); 00154 if (field) 00155 stk_classic::io::field_data_from_ioss(field, sides, block, *I); 00156 } 00157 } 00158 } 00159 } 00160 00161 void process_surface_entity(const Ioss::SideSet* sset, stk_classic::mesh::BulkData & bulk) 00162 { 00163 if (stk_classic::io::db_api_int_size(sset) == 4) 00164 process_surface_entity(sset, bulk, (int)0); 00165 else 00166 process_surface_entity(sset, bulk, (int64_t)0); 00167 } 00168 00169 void process_nodeblocks(Ioss::Region ®ion, stk_classic::mesh::fem::FEMMetaData &fem_meta) 00170 { 00171 const Ioss::NodeBlockContainer& node_blocks = region.get_node_blocks(); 00172 assert(node_blocks.size() == 1); 00173 00174 Ioss::NodeBlock *nb = node_blocks[0]; 00175 00176 assert(nb->field_exists("mesh_model_coordinates")); 00177 Ioss::Field coordinates = nb->get_field("mesh_model_coordinates"); 00178 int spatial_dim = coordinates.transformed_storage()->component_count(); 00179 00180 stk_classic::mesh::Field<double,stk_classic::mesh::Cartesian> & coord_field = 00181 fem_meta.declare_field<stk_classic::mesh::Field<double,stk_classic::mesh::Cartesian> >("coordinates"); 00182 00183 stk_classic::mesh::put_field( coord_field, fem_meta.node_rank(), fem_meta.universal_part(), spatial_dim); 00184 stk_classic::io::define_io_fields(nb, Ioss::Field::ATTRIBUTE, fem_meta.universal_part(), 0); 00185 } 00186 00187 void process_nodeblocks(Ioss::Region ®ion, stk_classic::mesh::BulkData &bulk) 00188 { 00189 // This must be called after the "process_element_blocks" call 00190 // since there may be nodes that exist in the database that are 00191 // not part of the analysis mesh due to subsetting of the element 00192 // blocks. 00193 00194 const stk_classic::mesh::fem::FEMMetaData &fem_meta = stk_classic::mesh::fem::FEMMetaData::get(bulk); 00195 00196 const Ioss::NodeBlockContainer& node_blocks = region.get_node_blocks(); 00197 assert(node_blocks.size() == 1); 00198 00199 Ioss::NodeBlock *nb = node_blocks[0]; 00200 00201 std::vector<stk_classic::mesh::Entity*> nodes; 00202 stk_classic::io::get_entity_list(nb, fem_meta.node_rank(), bulk, nodes); 00203 00204 stk_classic::mesh::Field<double,stk_classic::mesh::Cartesian> *coord_field = 00205 fem_meta.get_field<stk_classic::mesh::Field<double,stk_classic::mesh::Cartesian> >("coordinates"); 00206 00207 stk_classic::io::field_data_from_ioss(coord_field, nodes, nb, "mesh_model_coordinates"); 00208 00209 // Add all attributes as fields. 00210 // If the only attribute is 'attribute', then add it; otherwise the other attributes are the 00211 // named components of the 'attribute' field, so add them instead. 00212 Ioss::NameList names; 00213 nb->field_describe(Ioss::Field::ATTRIBUTE, &names); 00214 for(Ioss::NameList::const_iterator I = names.begin(); I != names.end(); ++I) { 00215 if(*I == "attribute" && names.size() > 1) 00216 continue; 00217 stk_classic::mesh::FieldBase *field = fem_meta.get_field<stk_classic::mesh::FieldBase> (*I); 00218 if (field) 00219 stk_classic::io::field_data_from_ioss(field, nodes, nb, *I); 00220 } 00221 } 00222 00223 // ======================================================================== 00224 void process_elementblocks(Ioss::Region ®ion, stk_classic::mesh::fem::FEMMetaData &fem_meta) 00225 { 00226 const Ioss::ElementBlockContainer& elem_blocks = region.get_element_blocks(); 00227 stk_classic::io::default_part_processing(elem_blocks, fem_meta); 00228 } 00229 00230 template <typename INT> 00231 void process_elementblocks(Ioss::Region ®ion, stk_classic::mesh::BulkData &bulk, INT /*dummy*/) 00232 { 00233 const stk_classic::mesh::fem::FEMMetaData& fem_meta = stk_classic::mesh::fem::FEMMetaData::get(bulk); 00234 00235 const Ioss::ElementBlockContainer& elem_blocks = region.get_element_blocks(); 00236 for(Ioss::ElementBlockContainer::const_iterator it = elem_blocks.begin(); 00237 it != elem_blocks.end(); ++it) { 00238 Ioss::ElementBlock *entity = *it; 00239 00240 if (stk_classic::io::include_entity(entity)) { 00241 const std::string &name = entity->name(); 00242 stk_classic::mesh::Part* const part = fem_meta.get_part(name); 00243 assert(part != NULL); 00244 00245 const CellTopologyData* cell_topo = stk_classic::io::get_cell_topology(*part); 00246 if (cell_topo == NULL) { 00247 std::ostringstream msg ; 00248 msg << " INTERNAL_ERROR: Part " << part->name() << " returned NULL from get_cell_topology()"; 00249 throw std::runtime_error( msg.str() ); 00250 } 00251 00252 std::vector<INT> elem_ids ; 00253 std::vector<INT> connectivity ; 00254 00255 entity->get_field_data("ids", elem_ids); 00256 entity->get_field_data("connectivity", connectivity); 00257 00258 size_t element_count = elem_ids.size(); 00259 int nodes_per_elem = cell_topo->node_count ; 00260 00261 std::vector<stk_classic::mesh::EntityId> id_vec(nodes_per_elem); 00262 std::vector<stk_classic::mesh::Entity*> elements(element_count); 00263 00264 for(size_t i=0; i<element_count; ++i) { 00265 INT *conn = &connectivity[i*nodes_per_elem]; 00266 std::copy(&conn[0], &conn[0+nodes_per_elem], id_vec.begin()); 00267 elements[i] = &stk_classic::mesh::fem::declare_element(bulk, *part, elem_ids[i], &id_vec[0]); 00268 } 00269 00270 // Add all element attributes as fields. 00271 // If the only attribute is 'attribute', then add it; otherwise the other attributes are the 00272 // named components of the 'attribute' field, so add them instead. 00273 Ioss::NameList names; 00274 entity->field_describe(Ioss::Field::ATTRIBUTE, &names); 00275 for(Ioss::NameList::const_iterator I = names.begin(); I != names.end(); ++I) { 00276 if(*I == "attribute" && names.size() > 1) 00277 continue; 00278 stk_classic::mesh::FieldBase *field = fem_meta.get_field<stk_classic::mesh::FieldBase> (*I); 00279 if (field) 00280 stk_classic::io::field_data_from_ioss(field, elements, entity, *I); 00281 } 00282 } 00283 } 00284 } 00285 00286 // ======================================================================== 00287 // ======================================================================== 00288 void process_nodesets(Ioss::Region ®ion, stk_classic::mesh::fem::FEMMetaData &fem_meta) 00289 { 00290 const Ioss::NodeSetContainer& node_sets = region.get_nodesets(); 00291 stk_classic::io::default_part_processing(node_sets, fem_meta); 00292 00293 stk_classic::mesh::Field<double> & distribution_factors_field = 00294 fem_meta.declare_field<stk_classic::mesh::Field<double> >("distribution_factors"); 00295 stk_classic::io::set_field_role(distribution_factors_field, Ioss::Field::MESH); 00296 00302 for(Ioss::NodeSetContainer::const_iterator it = node_sets.begin(); 00303 it != node_sets.end(); ++it) { 00304 Ioss::NodeSet *entity = *it; 00305 00306 if (stk_classic::io::include_entity(entity)) { 00307 stk_classic::mesh::Part* const part = fem_meta.get_part(entity->name()); 00308 assert(part != NULL); 00309 assert(entity->field_exists("distribution_factors")); 00310 00311 stk_classic::mesh::put_field(distribution_factors_field, fem_meta.node_rank(), *part); 00312 } 00313 } 00314 } 00315 00316 // ======================================================================== 00317 // ======================================================================== 00318 void process_sidesets(Ioss::Region ®ion, stk_classic::mesh::fem::FEMMetaData &fem_meta) 00319 { 00320 const Ioss::SideSetContainer& side_sets = region.get_sidesets(); 00321 stk_classic::io::default_part_processing(side_sets, fem_meta); 00322 00323 for(Ioss::SideSetContainer::const_iterator it = side_sets.begin(); 00324 it != side_sets.end(); ++it) { 00325 Ioss::SideSet *entity = *it; 00326 00327 if (stk_classic::io::include_entity(entity)) { 00328 process_surface_entity(entity, fem_meta); 00329 } 00330 } 00331 } 00332 00333 // ======================================================================== 00334 template <typename INT> 00335 void process_nodesets(Ioss::Region ®ion, stk_classic::mesh::BulkData &bulk, INT /*dummy*/) 00336 { 00337 // Should only process nodes that have already been defined via the element 00338 // blocks connectivity lists. 00339 const Ioss::NodeSetContainer& node_sets = region.get_nodesets(); 00340 const stk_classic::mesh::fem::FEMMetaData &fem_meta = stk_classic::mesh::fem::FEMMetaData::get(bulk); 00341 00342 for(Ioss::NodeSetContainer::const_iterator it = node_sets.begin(); 00343 it != node_sets.end(); ++it) { 00344 Ioss::NodeSet *entity = *it; 00345 00346 if (stk_classic::io::include_entity(entity)) { 00347 const std::string & name = entity->name(); 00348 stk_classic::mesh::Part* const part = fem_meta.get_part(name); 00349 assert(part != NULL); 00350 stk_classic::mesh::PartVector add_parts( 1 , part ); 00351 00352 std::vector<INT> node_ids ; 00353 size_t node_count = entity->get_field_data("ids", node_ids); 00354 00355 std::vector<stk_classic::mesh::Entity*> nodes(node_count); 00356 stk_classic::mesh::EntityRank n_rank = fem_meta.node_rank(); 00357 for(size_t i=0; i<node_count; ++i) { 00358 nodes[i] = bulk.get_entity(n_rank, node_ids[i] ); 00359 if (nodes[i] != NULL) 00360 bulk.declare_entity(n_rank, node_ids[i], add_parts ); 00361 } 00362 00363 stk_classic::mesh::Field<double> *df_field = 00364 fem_meta.get_field<stk_classic::mesh::Field<double> >("distribution_factors"); 00365 00366 if (df_field != NULL) { 00367 stk_classic::io::field_data_from_ioss(df_field, nodes, entity, "distribution_factors"); 00368 } 00369 00370 // Add all attributes as fields. 00371 // If the only attribute is 'attribute', then add it; otherwise the other attributes are the 00372 // named components of the 'attribute' field, so add them instead. 00373 Ioss::NameList names; 00374 entity->field_describe(Ioss::Field::ATTRIBUTE, &names); 00375 for(Ioss::NameList::const_iterator I = names.begin(); I != names.end(); ++I) { 00376 if(*I == "attribute" && names.size() > 1) 00377 continue; 00378 stk_classic::mesh::FieldBase *field = fem_meta.get_field<stk_classic::mesh::FieldBase> (*I); 00379 if (field) 00380 stk_classic::io::field_data_from_ioss(field, nodes, entity, *I); 00381 } 00382 } 00383 } 00384 } 00385 00386 // ======================================================================== 00387 void process_sidesets(Ioss::Region ®ion, stk_classic::mesh::BulkData &bulk) 00388 { 00389 const Ioss::SideSetContainer& side_sets = region.get_sidesets(); 00390 00391 for(Ioss::SideSetContainer::const_iterator it = side_sets.begin(); 00392 it != side_sets.end(); ++it) { 00393 Ioss::SideSet *entity = *it; 00394 00395 if (stk_classic::io::include_entity(entity)) { 00396 process_surface_entity(entity, bulk); 00397 } 00398 } 00399 } 00400 00401 // ======================================================================== 00402 void put_field_data(stk_classic::mesh::BulkData &bulk, stk_classic::mesh::Part &part, 00403 stk_classic::mesh::EntityRank part_type, 00404 Ioss::GroupingEntity *io_entity, 00405 Ioss::Field::RoleType filter_role, 00406 const stk_classic::mesh::Selector *anded_selector=NULL) 00407 { 00408 std::vector<stk_classic::mesh::Entity*> entities; 00409 if (io_entity->type() == Ioss::SIDEBLOCK) { 00410 // Temporary Kluge to handle sideblocks which contain internally generated sides 00411 // where the "ids" field on the io_entity doesn't work to get the correct side... 00412 // NOTE: Could use this method for all entity types, but then need to correctly 00413 // specify whether shared entities are included/excluded (See IossBridge version). 00414 size_t num_sides = get_entities(part, bulk, entities, anded_selector); 00415 if (num_sides != (size_t)io_entity->get_property("entity_count").get_int()) { 00416 std::ostringstream msg ; 00417 msg << " INTERNAL_ERROR: Number of sides on part " << part.name() << " (" << num_sides 00418 << ") does not match number of sides in the associated Ioss SideBlock named " 00419 << io_entity->name() << " (" << io_entity->get_property("entity_count").get_int() 00420 << ")."; 00421 throw std::runtime_error( msg.str() ); 00422 } 00423 } else { 00424 stk_classic::io::get_entity_list(io_entity, part_type, bulk, entities); 00425 } 00426 00427 const stk_classic::mesh::fem::FEMMetaData &fem_meta = stk_classic::mesh::fem::FEMMetaData::get(bulk); 00428 const std::vector<stk_classic::mesh::FieldBase*> &fields = fem_meta.get_fields(); 00429 00430 std::vector<stk_classic::mesh::FieldBase *>::const_iterator I = fields.begin(); 00431 while (I != fields.end()) { 00432 const stk_classic::mesh::FieldBase *f = *I; ++I; 00433 stk_classic::io::field_data_to_ioss(f, entities, io_entity, f->name(), filter_role); 00434 } 00435 } 00436 00437 void internal_process_output_request(stk_classic::io::MeshData &mesh_data, 00438 stk_classic::mesh::BulkData &bulk, 00439 int step, 00440 const std::set<const stk_classic::mesh::Part*> &exclude) 00441 { 00442 Ioss::Region *region = mesh_data.m_output_region; 00443 region->begin_state(step); 00444 const stk_classic::mesh::fem::FEMMetaData &fem_meta = stk_classic::mesh::fem::FEMMetaData::get(bulk); 00445 00446 // Special processing for nodeblock (all nodes in model)... 00447 put_field_data(bulk, fem_meta.universal_part(), fem_meta.node_rank(), 00448 region->get_node_blocks()[0], Ioss::Field::Field::TRANSIENT, 00449 mesh_data.m_anded_selector); 00450 00451 // Now handle all non-nodeblock parts... 00452 const stk_classic::mesh::PartVector & all_parts = fem_meta.get_parts(); 00453 for ( stk_classic::mesh::PartVector::const_iterator 00454 ip = all_parts.begin(); ip != all_parts.end(); ++ip ) { 00455 00456 stk_classic::mesh::Part * const part = *ip; 00457 00458 // Check whether this part should be output to results database. 00459 if (stk_classic::io::is_part_io_part(*part) && !exclude.count(part)) { 00460 // Get Ioss::GroupingEntity corresponding to this part... 00461 Ioss::GroupingEntity *entity = region->get_entity(part->name()); 00462 if (entity != NULL && entity->type() != Ioss::SIDESET) { 00463 put_field_data(bulk, *part, stk_classic::io::part_primary_entity_rank(*part), 00464 entity, Ioss::Field::Field::TRANSIENT, 00465 mesh_data.m_anded_selector); 00466 } 00467 } 00468 } 00469 region->end_state(step); 00470 } 00471 00472 namespace stk_classic { 00473 namespace io { 00474 00475 MeshData::~MeshData() 00476 { 00477 delete m_input_region; 00478 delete m_output_region; 00479 } 00480 00481 void show_mesh_help() 00482 { 00483 std::cerr << "Options are:\n" 00484 << "\n" 00485 << "filename -- specify the name of the file from which to read the\n" 00486 << " mesh file. If the --directory option is specified, it will be\n" 00487 << " prepended to the filename unless the filename specifies an absolute path.\n" 00488 << "\n" 00489 << "gen:NxMxL -- internally generate a hex mesh of size N by M by L\n" 00490 << " intervals. See 'Generated Options' below for more options.\n" 00491 << "\n" 00492 << "Generated Options:\n" 00493 << "shell:xXyYzZ\n" 00494 << "The argument specifies whether there is a shell block\n" 00495 << "at the location. 'x' is minX, 'X' is maxX, etc.\n" 00496 << "\n" 00497 << "help -- no argument, shows valid options\n" 00498 << "\n" 00499 << "show -- no argument, prints out a summary of the settings used to\n" 00500 << "generate the mesh. The output will look similar to:\n" 00501 << " \"10x12x8|shell:xX|bbox:-10,-10,-10,10,10,10|show\"\n" 00502 << "\n" 00503 << " Mesh Parameters:\n" 00504 << "\tIntervals: 10 by 12 by 8\n" 00505 << "\tX = 2 * (0..10) + -10 Range: -10 <= X <= 10\n" 00506 << "\tY = 1.66667 * (0..12) + -10 Range: -10 <= Y <= 10\n" 00507 << "\tZ = 2.5 * (0..8) + -10 Range: -10 <= Z <= 10\n" 00508 << "\tNode Count (total) = 1287\n" 00509 << "\tElement Count (total) = 1152\n" 00510 << "\tBlock Count = 3\n" 00511 << "\n" 00512 << "shell:xXyYzZ \n" 00513 << "which specifies whether there is a shell block at that\n" 00514 << "location. 'x' is minimum x face, 'X' is maximum x face,\n" 00515 << "similarly for y and z. Note that the argument string is a\n" 00516 << "single multicharacter string. You can add multiple shell blocks\n" 00517 << "to a face, for example, shell:xxx would add three layered shell\n" 00518 << "blocks on the minimum x face. An error is output if a non\n" 00519 << "xXyYzZ character is found, but execution continues.\n" 00520 << "\n" 00521 << "zdecomp:n0 n1,n2,...,n#proc-1\n" 00522 << "which are the number of intervals in the z direction for each\n" 00523 << "processor in a pallel run. If this option is specified, then\n" 00524 << "the total number of intervals in the z direction is the sum of\n" 00525 << "the n0, n1, ... An interval count must be specified for each\n" 00526 << "processor. If this option is not specified, then the number of\n" 00527 << "intervals on each processor in the z direction is numZ/numProc\n" 00528 << "with the extras added to the lower numbered processors.\n" 00529 << "\n" 00530 << "scale:xs,ys,zs\n" 00531 << "which are the scale factors in the x, y, and z directions. All\n" 00532 << "three must be specified if this option is present.\n" 00533 << "\n" 00534 << "- offset -- argument = xoff, yoff, zoff which are the offsets in the\n" 00535 << "x, y, and z directions. All three must be specified if this option\n" 00536 << "is present.\n" 00537 << "\n" 00538 << "- bbox -- argument = xmin, ymin, zmin, xmax, ymax, zmax\n" 00539 << "which specify the lower left and upper right corners of\n" 00540 << "the bounding box for the generated mesh. This will\n" 00541 << "calculate the scale and offset which will fit the mesh in\n" 00542 << "the specified box. All calculations are based on the currently\n" 00543 << "active interval settings. If scale or offset or zdecomp\n" 00544 << "specified later in the option list, you may not get the\n" 00545 << "desired bounding box.\n" 00546 << "\n" 00547 << "- rotate -- argument = axis,angle,axis,angle,...\n" 00548 << "where axis is 'x', 'y', or 'z' and angle is the rotation angle in\n" 00549 << "degrees. Multiple rotations are cumulative. The composite rotation\n" 00550 << "matrix is applied at the time the coordinates are retrieved after\n" 00551 << "scaling and offset are applied.\n" 00552 << "\n" 00553 << "The unrotated coordinate of a node at grid location i,j,k is:\n" 00554 << "\n" 00555 << "\tx = x_scale * i + x_off,\n" 00556 << "\ty = z_scale * j + y_off,\n" 00557 << "\tz = z_scale * k + z_off,\n" 00558 << "\n" 00559 << "The extent of the unrotated mesh will be:\n" 00560 << "\n" 00561 << "\tx_off <= x <= x_scale * numX + x_off\n" 00562 << "\ty_off <= y <= y_scale * numY + y_off\n" 00563 << "\tz_off <= z <= z_scale * numZ + z_off\n" 00564 << "\n" 00565 << "If an unrecognized option is specified, an error message will be\n" 00566 << "output and execution will continue.\n" 00567 << "\n" 00568 << "An example of valid input is:\n" 00569 << "\n" 00570 << "\t\"10x20x40|scale:1,0.5,0.25|offset:-5,-5,-5|shell:xX\"\n" 00571 << "\n" 00572 << "\n" 00573 << "This would create a mesh with 10 intervals in x, 20 in y, 40 in z\n" 00574 << "The mesh would be centered on 0,0,0 with a range of 10 in each\n" 00575 << "direction. There would be a shell layer on the min and max\n" 00576 << "x faces.\n" 00577 << "\n" 00578 << "NOTE: All options are processed in the order they appear in\n" 00579 << "the parameters string (except rotate which is applied at the\n" 00580 << "time the coordinates are generated/retrieved)\n" 00581 << "\n"; 00582 } 00583 00584 void create_input_mesh(const std::string &mesh_type, 00585 const std::string &mesh_filename, 00586 stk_classic::ParallelMachine comm, 00587 stk_classic::mesh::fem::FEMMetaData &fem_meta, 00588 stk_classic::io::MeshData &mesh_data, 00589 bool lower_case_variable_names) 00590 { 00591 Ioss::Region *in_region = mesh_data.m_input_region; 00592 if (in_region == NULL) { 00593 // If in_region is NULL, then open the file; 00594 // If in_region is non-NULL, then user has given us a valid Ioss::Region that 00595 // should be used. 00596 Ioss::DatabaseIO *dbi = Ioss::IOFactory::create(mesh_type, mesh_filename, 00597 Ioss::READ_MODEL, comm, 00598 mesh_data.m_property_manager); 00599 00600 // set up the casing for variable names 00601 dbi->set_lower_case_variable_names(lower_case_variable_names); 00602 00603 if (dbi == NULL || !dbi->ok()) { 00604 std::cerr << "ERROR: Could not open database '" << mesh_filename 00605 << "' of type '" << mesh_type << "'\n"; 00606 Ioss::NameList db_types; 00607 Ioss::IOFactory::describe(&db_types); 00608 std::cerr << "\nSupported database types:\n\t"; 00609 for (Ioss::NameList::const_iterator IF = db_types.begin(); IF != db_types.end(); ++IF) { 00610 std::cerr << *IF << " "; 00611 } 00612 std::cerr << "\n\n"; 00613 } 00614 00615 // NOTE: 'in_region' owns 'dbi' pointer at this time... 00616 in_region = new Ioss::Region(dbi, "input_model"); 00617 mesh_data.m_input_region = in_region; 00618 } 00619 00620 size_t spatial_dimension = in_region->get_property("spatial_dimension").get_int(); 00621 initialize_spatial_dimension(fem_meta, spatial_dimension, stk_classic::mesh::fem::entity_rank_names(spatial_dimension)); 00622 00623 process_elementblocks(*in_region, fem_meta); 00624 process_nodeblocks(*in_region, fem_meta); 00625 process_sidesets(*in_region, fem_meta); 00626 process_nodesets(*in_region, fem_meta); 00627 } 00628 00629 void create_input_mesh(const std::string &mesh_type, 00630 const std::string &mesh_filename, 00631 stk_classic::ParallelMachine comm, 00632 stk_classic::mesh::fem::FEMMetaData &fem_meta, 00633 stk_classic::io::MeshData &mesh_data, 00634 const std::vector<std::string>& names_to_add, 00635 bool lower_case_variable_names) 00636 { 00637 Ioss::Region *in_region = mesh_data.m_input_region; 00638 if (in_region == NULL) { 00639 // If in_region is NULL, then open the file; 00640 // If in_region is non-NULL, then user has given us a valid Ioss::Region that 00641 // should be used. 00642 Ioss::DatabaseIO *dbi = Ioss::IOFactory::create(mesh_type, mesh_filename, 00643 Ioss::READ_MODEL, comm, 00644 mesh_data.m_property_manager); 00645 00646 // set up the casing for variable names 00647 dbi->set_lower_case_variable_names(lower_case_variable_names); 00648 00649 if (dbi == NULL || !dbi->ok()) { 00650 std::cerr << "ERROR: Could not open database '" << mesh_filename 00651 << "' of type '" << mesh_type << "'\n"; 00652 Ioss::NameList db_types; 00653 Ioss::IOFactory::describe(&db_types); 00654 std::cerr << "\nSupported database types:\n\t"; 00655 for (Ioss::NameList::const_iterator IF = db_types.begin(); IF != db_types.end(); ++IF) { 00656 std::cerr << *IF << " "; 00657 } 00658 std::cerr << "\n\n"; 00659 } 00660 00661 // NOTE: 'in_region' owns 'dbi' pointer at this time... 00662 in_region = new Ioss::Region(dbi, "input_model"); 00663 mesh_data.m_input_region = in_region; 00664 } 00665 00666 size_t spatial_dimension = in_region->get_property("spatial_dimension").get_int(); 00667 00668 std::vector<std::string> entity_rank_names = stk_classic::mesh::fem::entity_rank_names(spatial_dimension); 00669 00670 for(std::size_t i = 0; i < names_to_add.size(); i++) 00671 entity_rank_names.push_back(names_to_add[i]); 00672 00673 initialize_spatial_dimension(fem_meta, spatial_dimension, entity_rank_names); 00674 00675 process_elementblocks(*in_region, fem_meta); 00676 process_nodeblocks(*in_region, fem_meta); 00677 process_sidesets(*in_region, fem_meta); 00678 process_nodesets(*in_region, fem_meta); 00679 } 00680 00681 00682 void create_output_mesh(const std::string &filename, 00683 stk_classic::ParallelMachine comm, 00684 stk_classic::mesh::BulkData &bulk_data, 00685 MeshData &mesh_data, 00686 bool lower_case_variable_names) 00687 { 00688 Ioss::Region *out_region = NULL; 00689 00690 std::string out_filename = filename; 00691 if (filename.empty()) { 00692 out_filename = "default_output_mesh"; 00693 } else { 00694 // These filenames may be coming from the generated options which 00695 // may have forms similar to: "2x2x1|size:.05|height:-0.1,1" 00696 // Strip the name at the first "+:|," character: 00697 std::vector<std::string> tokens; 00698 stk_classic::util::tokenize(out_filename, "+|:,", tokens); 00699 out_filename = tokens[0]; 00700 } 00701 00702 Ioss::DatabaseIO *dbo = Ioss::IOFactory::create("exodusII", out_filename, 00703 Ioss::WRITE_RESULTS, 00704 comm, mesh_data.m_property_manager); 00705 // set up the casing for variable names 00706 dbo->set_lower_case_variable_names(lower_case_variable_names); 00707 00708 if (dbo == NULL || !dbo->ok()) { 00709 std::cerr << "ERROR: Could not open results database '" << out_filename 00710 << "' of type 'exodusII'\n"; 00711 std::exit(EXIT_FAILURE); 00712 } 00713 00714 // NOTE: 'out_region' owns 'dbo' pointer at this time... 00715 out_region = new Ioss::Region(dbo, "results_output"); 00716 00717 stk_classic::io::define_output_db(*out_region, bulk_data, mesh_data.m_input_region, mesh_data.m_anded_selector); 00718 stk_classic::io::write_output_db(*out_region, bulk_data, mesh_data.m_anded_selector); 00719 mesh_data.m_output_region = out_region; 00720 } 00721 00722 // ======================================================================== 00723 int process_output_request(MeshData &mesh_data, 00724 stk_classic::mesh::BulkData &bulk, 00725 double time, 00726 const std::set<const stk_classic::mesh::Part*> &exclude) 00727 { 00728 Ioss::Region *region = mesh_data.m_output_region; 00729 region->begin_mode(Ioss::STATE_TRANSIENT); 00730 00731 int out_step = region->add_state(time); 00732 internal_process_output_request(mesh_data, bulk, out_step,exclude); 00733 00734 region->end_mode(Ioss::STATE_TRANSIENT); 00735 00736 return out_step; 00737 } 00738 00739 // ======================================================================== 00740 void populate_bulk_data(stk_classic::mesh::BulkData &bulk_data, 00741 MeshData &mesh_data) 00742 { 00743 Ioss::Region *region = mesh_data.m_input_region; 00744 00745 if (region) { 00746 00747 bulk_data.modification_begin(); 00748 process_mesh_bulk_data(region, bulk_data); 00749 bulk_data.modification_end(); 00750 00751 } else { 00752 std::cerr << "INTERNAL ERROR: Mesh Input Region pointer is NULL in populate_bulk_data.\n"; 00753 std::exit(EXIT_FAILURE); 00754 } 00755 } 00756 00757 // ======================================================================== 00758 void process_mesh_bulk_data(Ioss::Region *region, stk_classic::mesh::BulkData &bulk_data) 00759 { 00760 bool ints64bit = db_api_int_size(region) == 8; 00761 if (ints64bit) { 00762 int64_t zero = 0; 00763 process_elementblocks(*region, bulk_data, zero); 00764 process_nodeblocks(*region, bulk_data); 00765 process_nodesets(*region, bulk_data, zero); 00766 process_sidesets(*region, bulk_data); 00767 } else { 00768 int zero = 0; 00769 process_elementblocks(*region, bulk_data, zero); 00770 process_nodeblocks(*region, bulk_data); 00771 process_nodesets(*region, bulk_data, zero); 00772 process_sidesets(*region, bulk_data); 00773 } 00774 } 00775 00776 namespace { 00777 // ======================================================================== 00778 // Transfer transient field data from mesh file for io_entity to 00779 // the corresponding stk_mesh entities If there is a stk_mesh 00780 // field with the same name as the database field. 00781 // Assumes that mesh is positioned at the correct state for reading. 00782 void internal_process_input_request(Ioss::GroupingEntity *io_entity, 00783 stk_classic::mesh::EntityRank entity_rank, 00784 stk_classic::mesh::BulkData &bulk) 00785 { 00786 assert(io_entity != NULL); 00787 std::vector<stk_classic::mesh::Entity*> entity_list; 00788 stk_classic::io::get_entity_list(io_entity, entity_rank, bulk, entity_list); 00789 00790 const stk_classic::mesh::fem::FEMMetaData &fem_meta = stk_classic::mesh::fem::FEMMetaData::get(bulk); 00791 00792 Ioss::NameList names; 00793 io_entity->field_describe(Ioss::Field::TRANSIENT, &names); 00794 for (Ioss::NameList::const_iterator I = names.begin(); I != names.end(); ++I) { 00795 stk_classic::mesh::FieldBase *field = fem_meta.get_field<stk_classic::mesh::FieldBase>(*I); 00796 if (field) { 00797 stk_classic::io::field_data_from_ioss(field, entity_list, io_entity, *I); 00798 } 00799 } 00800 } 00801 00802 void input_nodeblock_fields(Ioss::Region ®ion, stk_classic::mesh::BulkData &bulk) 00803 { 00804 const stk_classic::mesh::fem::FEMMetaData &fem_meta = stk_classic::mesh::fem::FEMMetaData::get(bulk); 00805 const Ioss::NodeBlockContainer& node_blocks = region.get_node_blocks(); 00806 assert(node_blocks.size() == 1); 00807 00808 Ioss::NodeBlock *nb = node_blocks[0]; 00809 internal_process_input_request(nb, fem_meta.node_rank(), bulk); 00810 } 00811 00812 void input_elementblock_fields(Ioss::Region ®ion, stk_classic::mesh::BulkData &bulk) 00813 { 00814 const stk_classic::mesh::fem::FEMMetaData &fem_meta = stk_classic::mesh::fem::FEMMetaData::get(bulk); 00815 const Ioss::ElementBlockContainer& elem_blocks = region.get_element_blocks(); 00816 for(size_t i=0; i < elem_blocks.size(); i++) { 00817 if (stk_classic::io::include_entity(elem_blocks[i])) { 00818 internal_process_input_request(elem_blocks[i], fem_meta.element_rank(), bulk); 00819 } 00820 } 00821 } 00822 00823 void input_nodeset_fields(Ioss::Region ®ion, stk_classic::mesh::BulkData &bulk) 00824 { 00825 const stk_classic::mesh::fem::FEMMetaData &fem_meta = stk_classic::mesh::fem::FEMMetaData::get(bulk); 00826 const Ioss::NodeSetContainer& nodesets = region.get_nodesets(); 00827 for(size_t i=0; i < nodesets.size(); i++) { 00828 if (stk_classic::io::include_entity(nodesets[i])) { 00829 internal_process_input_request(nodesets[i], fem_meta.node_rank(), bulk); 00830 } 00831 } 00832 } 00833 00834 void input_sideset_fields(Ioss::Region ®ion, stk_classic::mesh::BulkData &bulk) 00835 { 00836 const stk_classic::mesh::fem::FEMMetaData &fem_meta = stk_classic::mesh::fem::FEMMetaData::get(bulk); 00837 if (fem_meta.spatial_dimension() <= fem_meta.side_rank()) 00838 return; 00839 00840 const Ioss::SideSetContainer& side_sets = region.get_sidesets(); 00841 for(Ioss::SideSetContainer::const_iterator it = side_sets.begin(); 00842 it != side_sets.end(); ++it) { 00843 Ioss::SideSet *entity = *it; 00844 if (stk_classic::io::include_entity(entity)) { 00845 const Ioss::SideBlockContainer& blocks = entity->get_side_blocks(); 00846 for(size_t i=0; i < blocks.size(); i++) { 00847 if (stk_classic::io::include_entity(blocks[i])) { 00848 internal_process_input_request(blocks[i], fem_meta.side_rank(), bulk); 00849 } 00850 } 00851 } 00852 } 00853 } 00854 00855 void define_input_nodeblock_fields(Ioss::Region ®ion, stk_classic::mesh::fem::FEMMetaData &fem_meta) 00856 { 00857 const Ioss::NodeBlockContainer& node_blocks = region.get_node_blocks(); 00858 assert(node_blocks.size() == 1); 00859 00860 Ioss::NodeBlock *nb = node_blocks[0]; 00861 stk_classic::io::define_io_fields(nb, Ioss::Field::TRANSIENT, 00862 fem_meta.universal_part(), fem_meta.node_rank()); 00863 } 00864 00865 void define_input_elementblock_fields(Ioss::Region ®ion, stk_classic::mesh::fem::FEMMetaData &fem_meta) 00866 { 00867 const Ioss::ElementBlockContainer& elem_blocks = region.get_element_blocks(); 00868 for(size_t i=0; i < elem_blocks.size(); i++) { 00869 if (stk_classic::io::include_entity(elem_blocks[i])) { 00870 stk_classic::mesh::Part* const part = fem_meta.get_part(elem_blocks[i]->name()); 00871 assert(part != NULL); 00872 stk_classic::io::define_io_fields(elem_blocks[i], Ioss::Field::TRANSIENT, 00873 *part, part_primary_entity_rank(*part)); 00874 } 00875 } 00876 } 00877 00878 void define_input_nodeset_fields(Ioss::Region ®ion, stk_classic::mesh::fem::FEMMetaData &fem_meta) 00879 { 00880 const Ioss::NodeSetContainer& nodesets = region.get_nodesets(); 00881 for(size_t i=0; i < nodesets.size(); i++) { 00882 if (stk_classic::io::include_entity(nodesets[i])) { 00883 stk_classic::mesh::Part* const part = fem_meta.get_part(nodesets[i]->name()); 00884 assert(part != NULL); 00885 stk_classic::io::define_io_fields(nodesets[i], Ioss::Field::TRANSIENT, 00886 *part, part_primary_entity_rank(*part)); 00887 } 00888 } 00889 } 00890 00891 void define_input_sideset_fields(Ioss::Region ®ion, stk_classic::mesh::fem::FEMMetaData &fem_meta) 00892 { 00893 if (fem_meta.spatial_dimension() <= fem_meta.side_rank()) 00894 return; 00895 00896 const Ioss::SideSetContainer& side_sets = region.get_sidesets(); 00897 for(Ioss::SideSetContainer::const_iterator it = side_sets.begin(); 00898 it != side_sets.end(); ++it) { 00899 Ioss::SideSet *entity = *it; 00900 if (stk_classic::io::include_entity(entity)) { 00901 const Ioss::SideBlockContainer& blocks = entity->get_side_blocks(); 00902 for(size_t i=0; i < blocks.size(); i++) { 00903 if (stk_classic::io::include_entity(blocks[i])) { 00904 stk_classic::mesh::Part* const part = fem_meta.get_part(blocks[i]->name()); 00905 assert(part != NULL); 00906 stk_classic::io::define_io_fields(blocks[i], Ioss::Field::TRANSIENT, 00907 *part, part_primary_entity_rank(*part)); 00908 } 00909 } 00910 } 00911 } 00912 } 00913 00914 } 00915 00916 // ======================================================================== 00917 // Iterate over all Ioss entities in the input mesh database and 00918 // define a stk_field for all transient fields found. The stk 00919 // field will have the same name as the field on the database. 00920 // 00921 // Note that all fields found on the database will have a 00922 // corresponding stk field defined. If you want just a selected 00923 // subset of the defined fields, you will need to define the 00924 // fields manually. 00925 // 00926 // To populate the stk field with data from the database, call 00927 // process_input_request(). 00928 void define_input_fields(MeshData &mesh_data, stk_classic::mesh::fem::FEMMetaData &fem_meta) 00929 { 00930 Ioss::Region *region = mesh_data.m_input_region; 00931 if (region) { 00932 define_input_nodeblock_fields(*region, fem_meta); 00933 define_input_elementblock_fields(*region, fem_meta); 00934 define_input_nodeset_fields(*region, fem_meta); 00935 define_input_sideset_fields(*region, fem_meta); 00936 } else { 00937 std::cerr << "INTERNAL ERROR: Mesh Input Region pointer is NULL in process_input_request.\n"; 00938 std::exit(EXIT_FAILURE); 00939 } 00940 } 00941 00942 // ======================================================================== 00943 // Iterate over all fields defined in the stk mesh data structure. 00944 // If the field has the io_attribute set, then define that field 00945 // on the corresponding io entity on the output mesh database. 00946 // The database field will have the same name as the stk field. 00947 // 00948 // To export the data to the database, call 00949 // process_output_request(). 00950 00951 void define_output_fields(const MeshData &mesh_data, const stk_classic::mesh::fem::FEMMetaData &fem_meta, 00952 bool add_all_fields) 00953 { 00954 Ioss::Region *region = mesh_data.m_output_region; 00955 if (region) { 00956 region->begin_mode(Ioss::STATE_DEFINE_TRANSIENT); 00957 00958 // Special processing for nodeblock (all nodes in model)... 00959 stk_classic::io::ioss_add_fields(fem_meta.universal_part(), fem_meta.node_rank(), 00960 region->get_node_blocks()[0], 00961 Ioss::Field::TRANSIENT, add_all_fields); 00962 00963 const stk_classic::mesh::PartVector & all_parts = fem_meta.get_parts(); 00964 for ( stk_classic::mesh::PartVector::const_iterator 00965 ip = all_parts.begin(); ip != all_parts.end(); ++ip ) { 00966 00967 stk_classic::mesh::Part * const part = *ip; 00968 00969 // Check whether this part should be output to results database. 00970 if (stk_classic::io::is_part_io_part(*part)) { 00971 // Get Ioss::GroupingEntity corresponding to this part... 00972 Ioss::GroupingEntity *entity = region->get_entity(part->name()); 00973 if (entity != NULL) { 00974 stk_classic::io::ioss_add_fields(*part, part_primary_entity_rank(*part), 00975 entity, Ioss::Field::TRANSIENT, add_all_fields); 00976 } 00977 } 00978 } 00979 region->end_mode(Ioss::STATE_DEFINE_TRANSIENT); 00980 } else { 00981 std::cerr << "INTERNAL ERROR: Mesh Input Region pointer is NULL in process_input_request.\n"; 00982 std::exit(EXIT_FAILURE); 00983 } 00984 } 00985 // ======================================================================== 00986 void process_input_request(MeshData &mesh_data, stk_classic::mesh::BulkData &bulk, double time) 00987 { 00988 // Find the step on the database with time closest to the requested time... 00989 Ioss::Region *region = mesh_data.m_input_region; 00990 int step_count = region->get_property("state_count").get_int(); 00991 double delta_min = 1.0e30; 00992 int step_min = 0; 00993 for (int istep = 0; istep < step_count; istep++) { 00994 double state_time = region->get_state_time(istep+1); 00995 double delta = state_time - time; 00996 if (delta < 0.0) delta = -delta; 00997 if (delta < delta_min) { 00998 delta_min = delta; 00999 step_min = istep; 01000 if (delta == 0.0) break; 01001 } 01002 } 01003 // Exodus steps are 1-based; 01004 process_input_request(mesh_data, bulk, step_min+1); 01005 } 01006 01007 void process_input_request(MeshData &mesh_data, 01008 stk_classic::mesh::BulkData &bulk, 01009 int step) 01010 { 01011 if (step <= 0) 01012 return; 01013 01014 Ioss::Region *region = mesh_data.m_input_region; 01015 if (region) { 01016 bulk.modification_begin(); 01017 01018 input_mesh_fields(region, bulk, step); 01019 01020 bulk.modification_end(); 01021 01022 } else { 01023 std::cerr << "INTERNAL ERROR: Mesh Input Region pointer is NULL in process_input_request.\n"; 01024 std::exit(EXIT_FAILURE); 01025 } 01026 } 01027 01028 void input_mesh_fields(Ioss::Region *region, stk_classic::mesh::BulkData &bulk, 01029 double time) 01030 { 01031 // Find the step on the database with time closest to the requested time... 01032 int step_count = region->get_property("state_count").get_int(); 01033 double delta_min = 1.0e30; 01034 int step_min = 0; 01035 for (int istep = 0; istep < step_count; istep++) { 01036 double state_time = region->get_state_time(istep+1); 01037 double delta = state_time - time; 01038 if (delta < 0.0) delta = -delta; 01039 if (delta < delta_min) { 01040 delta_min = delta; 01041 step_min = istep; 01042 if (delta == 0.0) break; 01043 } 01044 } 01045 // Exodus steps are 1-based; 01046 input_mesh_fields(region, bulk, step_min+1); 01047 } 01048 01049 void input_mesh_fields(Ioss::Region *region, stk_classic::mesh::BulkData &bulk, 01050 int step) 01051 { 01052 // Pick which time index to read into solution field. 01053 region->begin_state(step); 01054 01055 input_nodeblock_fields(*region, bulk); 01056 input_elementblock_fields(*region, bulk); 01057 input_nodeset_fields(*region, bulk); 01058 input_sideset_fields(*region, bulk); 01059 01060 region->end_state(step); 01061 } 01062 01063 // ======================================================================== 01064 template <typename INT> 01065 void get_element_block_sizes(MeshData &mesh_data, 01066 std::vector<INT>& el_blocks) 01067 { 01068 Ioss::Region *io = mesh_data.m_input_region; 01069 const Ioss::ElementBlockContainer& elem_blocks = io->get_element_blocks(); 01070 for(Ioss::ElementBlockContainer::const_iterator it = elem_blocks.begin(); it != elem_blocks.end(); ++it) { 01071 Ioss::ElementBlock *entity = *it; 01072 if (stk_classic::io::include_entity(entity)) { 01073 el_blocks.push_back(entity->get_property("entity_count").get_int()); 01074 } 01075 } 01076 } 01077 template void get_element_block_sizes(MeshData &mesh_data, std::vector<int>& el_blocks); 01078 template void get_element_block_sizes(MeshData &mesh_data, std::vector<int64_t>& el_blocks); 01079 } // namespace io 01080 } // namespace stk_classic