void CrackFrontDefinition::calculateRThetaToCrackFront(const Point qp, const unsigned int node_index, Real & r, Real & theta) const { unsigned int num_nodes(_ordered_crack_front_nodes.size()); Point p = qp; Point closest_node(0.0); RealVectorValue closest_node_to_p; Node & crack_tip_node = _mesh.node(_ordered_crack_front_nodes[node_index]); RealVectorValue crack_tip_node_rot = rotateToCrackFrontCoords(crack_tip_node,node_index); RealVectorValue crack_front_edge = rotateToCrackFrontCoords(_tangent_directions[node_index],node_index); Point p_rot = rotateToCrackFrontCoords(p,node_index); p_rot = p_rot - crack_tip_node_rot; if (_treat_as_2d) { closest_node = crack_tip_node_rot; closest_node_to_p = p_rot; //Find r, the distance between the qp and the crack front RealVectorValue r_vec = p_rot; r = r_vec.size(); } else { // Loop over crack front nodes to find the one closest to the point qp Real min_dist = std::numeric_limits<Real>::max(); for (unsigned int nit = 0; nit != num_nodes; ++nit) { Node & crack_front_node = _mesh.node(_ordered_crack_front_nodes[nit]); RealVectorValue crack_node_to_current_node = p - crack_front_node; Real dist = crack_node_to_current_node.size(); if (dist < min_dist) { min_dist = dist; closest_node = crack_front_node; } } //Rotate coordinates to crack front coordinate system closest_node = rotateToCrackFrontCoords(closest_node,node_index); closest_node = closest_node - crack_tip_node_rot; //Find r, the distance between the qp and the crack front Real edge_length_sq = crack_front_edge.size_sq(); closest_node_to_p = p_rot - closest_node; Real perp = crack_front_edge * closest_node_to_p; Real dist_along_edge = perp / edge_length_sq; RealVectorValue point_on_edge = closest_node + crack_front_edge * dist_along_edge; RealVectorValue r_vec = p_rot - point_on_edge; r = r_vec.size(); } //Find theta, the angle between r and the crack front plane RealVectorValue crack_plane_normal = rotateToCrackFrontCoords(_crack_plane_normal,node_index); Real p_to_plane_dist = std::abs(closest_node_to_p*crack_plane_normal); //Determine if p is above or below the crack plane Real y_local = p_rot(1) - closest_node(1); //Determine if p is in front of or behind the crack front RealVectorValue p2(p_rot); p2(1) = 0; RealVectorValue p2_vec = p2 - closest_node; Real ahead = crack_front_edge(2) * p2_vec(0) - crack_front_edge(0) * p2_vec(2); Real x_local(0); if (ahead >= 0) x_local = 1; else x_local = -1; //Calculate theta based on in which quadrant in the crack front coordinate //system the qp is located if (x_local >= 0 && y_local >= 0) theta = std::asin(p_to_plane_dist/r); else if (x_local < 0 && y_local >= 0) theta = libMesh::pi - std::asin(p_to_plane_dist/r); else if (x_local < 0 && y_local < 0) theta = -(libMesh::pi - std::asin(p_to_plane_dist/r)); else if (x_local >= 0 && y_local < 0) theta = -std::asin(p_to_plane_dist/r); }
void CrackFrontDefinition::calculateRThetaToCrackFront(const Point qp, const unsigned int node_index, Real & r, Real & theta) const { unsigned int num_nodes(_ordered_crack_front_nodes.size()); Point p = qp; // Loop over nodes to find the two crack front nodes closest to the point qp Real mindist1(1.0e30); Real mindist2(1.0e30); Point closest_node1(0.0); Point closest_node2(0.0); for (unsigned int nit = 0; nit != num_nodes; ++nit) { Node & crack_front_node = _mesh.node(_ordered_crack_front_nodes[nit]); RealVectorValue crack_node_to_current_node = p - crack_front_node; Real dist = crack_node_to_current_node.size(); if (dist < mindist1) { mindist2 = mindist1; closest_node2 = closest_node1; mindist1 = dist; closest_node1 = crack_front_node; } else if (dist < mindist2 && dist != mindist1) { mindist2 = dist; closest_node2 = crack_front_node; } } //Rotate coordinates to crack front coordinate system closest_node1 = rotateToCrackFrontCoords(closest_node1,node_index); closest_node2 = rotateToCrackFrontCoords(closest_node2,node_index); if (closest_node1(2) > closest_node2(2)) { RealVectorValue tmp = closest_node2; closest_node2 = closest_node1; closest_node1 = tmp; } p = rotateToCrackFrontCoords(p,node_index); //Find r, the distance between the qp and the crack front RealVectorValue crack_front_edge = closest_node2 - closest_node1; Real edge_length_sq = crack_front_edge.size_sq(); RealVectorValue closest_node1_to_p = p - closest_node1; Real perp = crack_front_edge * closest_node1_to_p; Real dist_along_edge = perp / edge_length_sq; RealVectorValue point_on_edge = closest_node1 + crack_front_edge * dist_along_edge; RealVectorValue r_vec = p - point_on_edge; r = r_vec.size(); //Find theta, the angle between r and the crack front plane RealVectorValue crack_plane_normal = rotateToCrackFrontCoords(_crack_plane_normal,node_index); Real p_to_plane_dist = std::abs(closest_node1_to_p*crack_plane_normal); //Determine if p is above or below the crack plane Real y_local = p(1) - closest_node1(1); //Determine if p is in front of or behind the crack front RealVectorValue p2(p); p2(1) = 0; RealVectorValue p2_vec = p2 - closest_node1; Real ahead = crack_front_edge(2) * p2_vec(0) - crack_front_edge(0) * p2_vec(2); Real x_local(0); if (ahead >= 0) x_local = 1; else x_local = -1; //Calculate theta based on in which quadrant in the crack front coordinate //system the qp is located if (x_local >= 0 && y_local >= 0) theta = std::asin(p_to_plane_dist/r); else if (x_local < 0 && y_local >= 0) theta = libMesh::pi - std::asin(p_to_plane_dist/r); else if (x_local < 0 && y_local < 0) theta = -(libMesh::pi - std::asin(p_to_plane_dist/r)); else if (x_local >= 0 && y_local < 0) theta = -std::asin(p_to_plane_dist/r); }
//---------------------------------------------------------------------------// // Hex-8 test. TEUCHOS_UNIT_TEST( STKMeshEntityIterator, hex_8_test ) { // Extract the raw mpi communicator. Teuchos::RCP<const Teuchos::Comm<int> > comm = getDefaultComm<int>(); Teuchos::RCP<const Teuchos::MpiComm<int> > mpi_comm = Teuchos::rcp_dynamic_cast< const Teuchos::MpiComm<int> >( comm ); Teuchos::RCP<const Teuchos::OpaqueWrapper<MPI_Comm> > opaque_comm = mpi_comm->getRawMpiComm(); MPI_Comm raw_comm = (*opaque_comm)(); // Create meta data. int space_dim = 3; stk::mesh::MetaData meta_data( space_dim ); // Make two parts. std::string p1_name = "part_1"; stk::mesh::Part& part_1 = meta_data.declare_part( p1_name ); stk::mesh::set_topology( part_1, stk::topology::HEX_8 ); std::string p2_name = "part_2"; stk::mesh::Part& part_2 = meta_data.declare_part( p2_name ); // Make a coordinate field. stk::mesh::Field<double, stk::mesh::Cartesian3d>& coord_field = meta_data.declare_field< stk::mesh::Field<double, stk::mesh::Cartesian3d> >( stk::topology::NODE_RANK, "coordinates"); meta_data.set_coordinate_field( &coord_field ); stk::mesh::put_field( coord_field, part_1 ); meta_data.commit(); // Create bulk data. Teuchos::RCP<stk::mesh::BulkData> bulk_data = Teuchos::rcp( new stk::mesh::BulkData(meta_data,raw_comm) ); bulk_data->modification_begin(); // Make a hex-8. int comm_rank = comm->getRank(); stk::mesh::EntityId hex_id = 23 + comm_rank; stk::mesh::Entity hex_entity = bulk_data->declare_entity( stk::topology::ELEM_RANK, hex_id, part_1 ); int num_nodes = 8; Teuchos::Array<stk::mesh::EntityId> node_ids( num_nodes ); Teuchos::Array<stk::mesh::Entity> nodes( num_nodes ); for ( int i = 0; i < num_nodes; ++i ) { node_ids[i] = num_nodes*comm_rank + i + 5; nodes[i] = bulk_data->declare_entity( stk::topology::NODE_RANK, node_ids[i], part_1 ); bulk_data->declare_relation( hex_entity, nodes[i], i ); } bulk_data->modification_end(); // Create the node coordinates. double* node_coords = 0; node_coords = stk::mesh::field_data( coord_field, nodes[0] ); node_coords[0] = 0.0; node_coords[1] = 0.0; node_coords[2] = 0.0; node_coords = stk::mesh::field_data( coord_field, nodes[1] ); node_coords[0] = 1.0; node_coords[1] = 0.0; node_coords[2] = 0.0; node_coords = stk::mesh::field_data( coord_field, nodes[2] ); node_coords[0] = 1.0; node_coords[1] = 1.0; node_coords[2] = 0.0; node_coords = stk::mesh::field_data( coord_field, nodes[3] ); node_coords[0] = 0.0; node_coords[1] = 1.0; node_coords[2] = 0.0; node_coords = stk::mesh::field_data( coord_field, nodes[4] ); node_coords[0] = 0.0; node_coords[1] = 0.0; node_coords[2] = 1.0; node_coords = stk::mesh::field_data( coord_field, nodes[5] ); node_coords[0] = 1.0; node_coords[1] = 0.0; node_coords[2] = 1.0; node_coords = stk::mesh::field_data( coord_field, nodes[6] ); node_coords[0] = 1.0; node_coords[1] = 1.0; node_coords[2] = 1.0; node_coords = stk::mesh::field_data( coord_field, nodes[7] ); node_coords[0] = 0.0; node_coords[1] = 1.0; node_coords[2] = 1.0; // Make a list of hexes. unsigned num_hex = 2; std::vector<stk::mesh::Entity> hex_entities( num_hex, hex_entity ); // Make a range for the iterators. Teuchos::RCP<DataTransferKit::STKMeshEntityIteratorRange> iterator_range = Teuchos::rcp( new DataTransferKit::STKMeshEntityIteratorRange() ); iterator_range->d_stk_entities = hex_entities; // Test the name predicate for part 1. DataTransferKit::STKPartNamePredicate part_1_name_pred( Teuchos::Array<std::string>(1,p1_name), bulk_data ); DataTransferKit::EntityIterator part_1_name_iterator = DataTransferKit::STKMeshEntityIterator( iterator_range, bulk_data, part_1_name_pred.getFunction() ); TEST_EQUALITY( part_1_name_iterator.size(), num_hex ); // Test the name predicate for part 2. DataTransferKit::STKPartNamePredicate part_2_name_pred( Teuchos::Array<std::string>(2,p2_name), bulk_data ); DataTransferKit::EntityIterator part_2_name_iterator = DataTransferKit::STKMeshEntityIterator( iterator_range, bulk_data, part_2_name_pred.getFunction() ); TEST_EQUALITY( part_2_name_iterator.size(), 0 ); // Test the part vector predicate for part 1. stk::mesh::PartVector p1_vec( 1, &part_1 ); DataTransferKit::STKPartVectorPredicate part_1_vec_pred( p1_vec ); DataTransferKit::EntityIterator part_1_vec_iterator = DataTransferKit::STKMeshEntityIterator( iterator_range, bulk_data, part_1_vec_pred.getFunction() ); TEST_EQUALITY( part_1_vec_iterator.size(), num_hex ); // Test the part vector predicate for part 2. stk::mesh::PartVector p2_vec( 2, &part_2 ); DataTransferKit::STKPartVectorPredicate part_2_vec_pred( p2_vec ); DataTransferKit::EntityIterator part_2_vec_iterator = DataTransferKit::STKMeshEntityIterator( iterator_range, bulk_data, part_2_vec_pred.getFunction() ); TEST_EQUALITY( part_2_vec_iterator.size(), 0 ); // Test a part vector with 2 part 1's. stk::mesh::PartVector p11_vec( 2, &part_1 ); DataTransferKit::STKPartVectorPredicate part_11_vec_pred( p11_vec ); DataTransferKit::EntityIterator part_11_vec_iterator = DataTransferKit::STKMeshEntityIterator( iterator_range, bulk_data, part_11_vec_pred.getFunction() ); TEST_EQUALITY( part_11_vec_iterator.size(), num_hex ); // Test a part vector with a part 1 and part 2 stk::mesh::PartVector p12_vec( 2 ); p12_vec[0] = &part_1; p12_vec[1] = &part_2; DataTransferKit::STKPartVectorPredicate part_12_vec_pred( p12_vec ); DataTransferKit::EntityIterator part_12_vec_iterator = DataTransferKit::STKMeshEntityIterator( iterator_range, bulk_data, part_12_vec_pred.getFunction() ); TEST_EQUALITY( part_12_vec_iterator.size(), 0 ); // Test the part selector predicate for part 1. stk::mesh::Selector p1_sel( part_1 ); DataTransferKit::STKSelectorPredicate part_1_sel_pred( p1_sel ); DataTransferKit::EntityIterator part_1_sel_iterator = DataTransferKit::STKMeshEntityIterator( iterator_range, bulk_data, part_1_sel_pred.getFunction() ); TEST_EQUALITY( part_1_sel_iterator.size(), num_hex ); // Test the part selector predicate for part 2. stk::mesh::Selector p2_sel( part_2 ); DataTransferKit::STKSelectorPredicate part_2_sel_pred( p2_sel ); DataTransferKit::EntityIterator part_2_sel_iterator = DataTransferKit::STKMeshEntityIterator( iterator_range, bulk_data, part_2_sel_pred.getFunction() ); TEST_EQUALITY( part_2_sel_iterator.size(), 0 ); }