示例#1
0
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;
  }
}
示例#2
0
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 );
}