bool use_case_1_driver( MPI_Comm comm , const std::string& mesh_options ) { if ( 0 == stk_classic::parallel_machine_rank( comm ) ) { std::cout << "stk_linsys use case 1" << std::endl << " Number Processes = " << stk_classic::parallel_machine_size( comm ) << std::endl ; } //-------------------------------------------------------------------- { //------------------------------------------------------------------ // Declare the mesh meta data: element blocks and associated fields stk_classic::mesh::fem::FEMMetaData fem_meta; fem_meta.FEM_initialize(SpatialDim, stk_classic::mesh::fem::entity_rank_names(SpatialDim) ) ; stk_classic::mesh::MetaData & mesh_meta_data = stk_classic::mesh::fem::FEMMetaData::get_meta_data(fem_meta); const stk_classic::mesh::EntityRank element_rank = fem_meta.element_rank(); //-------------------------------- // Element-block declarations typically occur when reading the // mesh-file meta-data, and thus won't usually appear in application code. // Declaring the element blocks and associating an element traits // with each element block. stk_classic::mesh::Part & universal = fem_meta.universal_part(); stk_classic::mesh::Part & block_hex = fem_meta.declare_part("block_1", element_rank); stk_classic::mesh::Part & block_quad_shell = fem_meta.declare_part("block_2", element_rank); stk_classic::mesh::fem::CellTopology hex_top(shards::getCellTopologyData<shards::Hexahedron<> >()); stk_classic::mesh::fem::CellTopology qshell_top(shards::getCellTopologyData<shards::ShellQuadrilateral<> >()); stk_classic::mesh::fem::set_cell_topology( block_hex, hex_top ); stk_classic::mesh::fem::set_cell_topology( block_quad_shell, qshell_top ); //-------------------------------- // Declaring fields of specified types on all nodes: VectorFieldType & coordinates_field = stk_classic::mesh::put_field( fem_meta.declare_field< VectorFieldType >( "coordinates" ) , stk_classic::mesh::fem::FEMMetaData::NODE_RANK , universal , SpatialDim ); VectorFieldType & displacements_field = stk_classic::mesh::put_field( fem_meta.declare_field< VectorFieldType >( "displacements" ) , stk_classic::mesh::fem::FEMMetaData::NODE_RANK , universal , SpatialDim ); //-------------------------------- // Put a scalar "pressure" field on all elements, just to use in demonstrating // DOF mappings below: ScalarFieldType & pressure_field = stk_classic::mesh::put_field( fem_meta.declare_field< ScalarFieldType >("pressure"), element_rank, universal); //-------------------------------- // rotation_field only exists on the shell-nodes: VectorFieldType & rotation_field = stk_classic::mesh::put_field( fem_meta.declare_field< VectorFieldType >( "rotation" ), stk_classic::mesh::fem::FEMMetaData::NODE_RANK , block_quad_shell , SpatialDim ); //-------------------------------- // Commit (finalize) the meta data. Is now ready to be used // in the creation and management of mesh bulk data. fem_meta.commit(); //------------------------------------------------------------------ // stk_classic::mesh::BulkData bulk data conforming to the meta data. stk_classic::mesh::BulkData mesh_bulk_data( mesh_meta_data , comm ); // In a typical app, the mesh would be read from file at this point. // But in this use-case, we generate the mesh and initialize // field data to use-case defined values. use_case_1_generate_mesh( mesh_options , mesh_bulk_data , coordinates_field , block_hex , block_quad_shell ); use_case_1_initialize_data( mesh_bulk_data , coordinates_field , displacements_field , rotation_field ); mesh_bulk_data.modification_end(); //------------------------------------------------------------------ const unsigned myProc = mesh_bulk_data.parallel_rank(); stk_classic::linsys::DofMapper dof_mapper(comm); if (myProc == 0) { std::cout << "Adding DOF mappings for displacements field for all locally-used " << "(owned and shared) nodes..." << std::endl; } const stk_classic::mesh::Selector select_used = fem_meta.locally_owned_part() | fem_meta.globally_shared_part(); dof_mapper.add_dof_mappings(mesh_bulk_data, select_used, stk_classic::mesh::fem::FEMMetaData::NODE_RANK, displacements_field); if (myProc == 0) { std::cout << "Adding DOF mappings for pressure field for all locally-owned " << " elements..." << std::endl; } stk_classic::mesh::Selector select_owned = fem_meta.locally_owned_part(); dof_mapper.add_dof_mappings(mesh_bulk_data, select_owned, element_rank, pressure_field); dof_mapper.finalize(); if (myProc == 0) { std::cout << "Global Number of Indices: " << dof_mapper.get_fei_VectorSpace()->getGlobalNumIndices() << std::endl; } std::vector<stk_classic::mesh::Entity*> nodes; stk_classic::mesh::get_entities(mesh_bulk_data, stk_classic::mesh::fem::FEMMetaData::NODE_RANK, nodes); std::vector<stk_classic::mesh::Entity*> elems; stk_classic::mesh::get_entities(mesh_bulk_data, element_rank, elems); int global_index = 0; for(size_t i=0; i<nodes.size(); i+=1000) { //is the i-th node in the locally-used part? If not, continue. if (! select_used( nodes[i]->bucket())) continue; global_index = dof_mapper.get_global_index(stk_classic::mesh::fem::FEMMetaData::NODE_RANK, nodes[i]->identifier(), displacements_field); std::cout << "Proc " << myProc << ", global index for node " << nodes[i]->identifier() << ", field '"<<displacements_field.name()<<"' is: " << global_index << std::endl; } for(size_t i=0; i<elems.size(); i+=1000) { //is the i-th elem in the locally-owned part? If not, continue. if (!elems[i]->bucket().member(fem_meta.locally_owned_part())) continue; global_index = dof_mapper.get_global_index(element_rank, elems[i]->identifier(), pressure_field); std::cout << "Proc " << myProc << ", global index for element " << elems[i]->identifier() << ", field '"<<pressure_field.name()<<"' is: " << global_index << std::endl; } if (mesh_options == "10x10x10+shell:y") { return dof_mapper.get_fei_VectorSpace()->getGlobalNumIndices() == 5093; } return true; } }
void testDofMapper( MPI_Comm comm ) { //First create and fill MetaData and BulkData objects: const unsigned bucket_size = 100; //for a real application mesh, bucket_size would be much bigger... stk::mesh::MetaData meta_data( stk::mesh::fem_entity_rank_names() ); stk::mesh::BulkData bulk_data( meta_data, comm, bucket_size ); fill_utest_mesh_meta_data( meta_data ); fill_utest_mesh_bulk_data( bulk_data ); stk::mesh::Selector selector = meta_data.locally_owned_part() | meta_data.globally_shared_part() ; std::vector<unsigned> count; stk::mesh::count_entities(selector, bulk_data, count); STKUNIT_ASSERT_EQUAL( count[stk::mesh::Element], (unsigned)4 ); STKUNIT_ASSERT_EQUAL( count[stk::mesh::Node], (unsigned)20 ); std::vector<stk::mesh::Entity*> nodes; stk::mesh::get_entities(bulk_data, stk::mesh::Node, nodes); stk::mesh::ScalarField* temperature_field = meta_data.get_field<stk::mesh::ScalarField>("temperature"); //Now we're ready to test the DofMapper: stk::linsys::DofMapper dof_mapper(comm); const stk::mesh::Selector select_used = meta_data.locally_owned_part() | meta_data.globally_shared_part(); dof_mapper.add_dof_mappings(bulk_data, select_used, stk::mesh::Node, *temperature_field); stk::mesh::EntityRank ent_type; stk::mesh::EntityId ent_id; const stk::mesh::FieldBase* field = NULL; int offset_into_field; int index = 0; //DofMapper::get_dof can't be called until after DofMapper::finalize() has //been called. //We'll call it now to verify that an exception is thrown: std::cout << "Testing error condition: " << std::endl; STKUNIT_ASSERT_THROW(dof_mapper.get_dof(index, ent_type, ent_id, field, offset_into_field), std::runtime_error ); std::cout << "...Completed testing error condition." << std::endl; dof_mapper.finalize(); //find a node that is in the locally-used part: size_t i_node = 0; while(! select_used( nodes[i_node]->bucket() ) && i_node<nodes.size()) { ++i_node; } //test the get_global_index function: stk::mesh::EntityId node_id = nodes[i_node]->identifier(); index = dof_mapper.get_global_index(stk::mesh::Node, node_id, *temperature_field); STKUNIT_ASSERT_EQUAL( index, (int)(node_id-1) ); std::cout << "Testing error condition: " << std::endl; //call DofMapper::get_global_index with a non-existent ID and verify that an //exception is thrown: STKUNIT_ASSERT_THROW(dof_mapper.get_global_index(stk::mesh::Node, (stk::mesh::EntityId)999999, *temperature_field), std::runtime_error); std::cout << "...Completed testing error condition." << std::endl; int numProcs = 1; numProcs = stk::parallel_machine_size( MPI_COMM_WORLD ); fei::SharedPtr<fei::VectorSpace> fei_vspace = dof_mapper.get_fei_VectorSpace(); int numIndices = fei_vspace->getGlobalNumIndices(); STKUNIT_ASSERT_EQUAL( numIndices, (int)(numProcs*20 - (numProcs-1)*4) ); dof_mapper.get_dof(index, ent_type, ent_id, field, offset_into_field); STKUNIT_ASSERT_EQUAL( ent_type, nodes[i_node]->entity_rank() ); STKUNIT_ASSERT_EQUAL( ent_id, nodes[i_node]->identifier() ); STKUNIT_ASSERT_EQUAL( field->name() == temperature_field->name(), true ); STKUNIT_ASSERT_EQUAL( offset_into_field, (int)0 ); }