//---------------------------------------------------------------------------- // // Random fracture criterion function. // bool RandomCriterion::computeFractureCriterion(stk::mesh::Entity& entity, double p) { // Fracture only defined on the boundary of the elements stk::mesh::EntityRank rank = entity.entity_rank(); assert(rank == num_dim_ - 1); stk::mesh::PairIterRelation neighbor_elems = entity.relations(element_rank_); // Need an element on each side if(neighbor_elems.size() != 2) return false; bool is_open = false; // All we need to do is generate a number between 0 and 1 double random = 0.5 + 0.5 * Teuchos::ScalarTraits<double>::random(); if(random < p) { is_open = true; } return is_open; }
bool gather_field_data(unsigned expected_num_rel, const field_type & field, const stk::mesh::Entity & entity, typename stk::mesh::FieldTraits<field_type>::data_type * dst, stk::mesh::EntityRank entity_rank, const int dim) { typedef typename stk::mesh::FieldTraits<field_type>::data_type T; stk::mesh::PairIterRelation rel = entity.relations(entity_rank); bool result = expected_num_rel == (unsigned) rel.size(); if (result) { // Iterate over field data for each related entity and copy data // into src for one entity at a time T * const dst_end = dst + dim * expected_num_rel; for (; dst < dst_end; ++rel, dst += dim) { const T* src = field_data(field, *rel->entity()); if (!src) { break; } // FIXME: if (dim == 1) stk::Copy<1>(dst, src); if (dim == 2) stk::Copy<2>(dst, src); if (dim == 3) stk::Copy<3>(dst, src); } result = dst == dst_end; } return result; }
bool AAdapt::STKUnifUnrefineField::operator()(const stk::mesh::Entity element, stk::mesh::FieldBase* field, const stk::mesh::BulkData& bulkData) { const stk::mesh::PairIterRelation elem_nodes = element.relations(stk::topology::NODE_RANK); unsigned num_node = elem_nodes.size(); double* f_data = stk::percept::PerceptMesh::field_data_entity(field, element); Albany::AbstractSTKFieldContainer::VectorFieldType* coordField = m_eMesh.get_coordinates_field(); bool found = true; for(unsigned inode = 0; inode < num_node; inode++) { stk::mesh::Entity node = * elem_nodes[ inode ].entity(); double* coord_data = stk::percept::PerceptMesh::field_data(coordField, node); if(coord_data[0] < 0.0 || coord_data[1] < 0.0) { // || coord_data[2] > 1.1) found = false; break; } } if(found) f_data[0] = -1.0; else f_data[0] = 0.0; return false; // don't terminate the loop }
int IEdgeAdapter::markUnrefine(const stk::mesh::Entity& element) { const CellTopologyData * const cell_topo_data = stk::percept::PerceptMesh::get_cell_topology(element); CellTopology cell_topo(cell_topo_data); const mesh::PairIterRelation elem_nodes = element.relations(stk::mesh::fem::FEMMetaData::NODE_RANK); VectorFieldType* coordField = m_eMesh.get_coordinates_field(); unsigned numSubDimNeededEntities = 0; numSubDimNeededEntities = cell_topo_data->edge_count; bool unrefAllEdges = true; for (unsigned iSubDimOrd = 0; iSubDimOrd < numSubDimNeededEntities; iSubDimOrd++) { stk::mesh::Entity & node0 = *elem_nodes[cell_topo_data->edge[iSubDimOrd].node[0]].entity(); stk::mesh::Entity & node1 = *elem_nodes[cell_topo_data->edge[iSubDimOrd].node[1]].entity(); double * const coord0 = stk::mesh::field_data( *coordField , node0 ); double * const coord1 = stk::mesh::field_data( *coordField , node1 ); int markInfo = mark(element, iSubDimOrd, node0, node1, coord0, coord1, 0); bool do_unref = markInfo & DO_UNREFINE; if (!do_unref) { unrefAllEdges = false; break; } } if (unrefAllEdges) return -1; else return 0; }
bool AAdapt::STKUnifRefineField::operator()(const stk::mesh::Entity element, stk::mesh::FieldBase* field, const stk::mesh::BulkData& bulkData) { /* double plane_point[3] = {2, 0, 0}; double plane_normal[3] = {1, .5, -.5}; */ double plane_point[3] = {0, 0.7, 0}; double plane_normal[3] = {0, 1, 0}; const stk::mesh::PairIterRelation elem_nodes = element.relations(stk::topology::NODE_RANK); unsigned num_node = elem_nodes.size(); double* f_data = stk::percept::PerceptMesh::field_data_entity(field, element); Albany::AbstractSTKFieldContainer::VectorFieldType* coordField = m_eMesh.get_coordinates_field(); bool found = false; for(unsigned inode = 0; inode < num_node - 1; inode++) { stk::mesh::Entity node_i = * elem_nodes[ inode ].entity(); double* coord_data_i = stk::percept::PerceptMesh::field_data(coordField, node_i); for(unsigned jnode = inode + 1; jnode < num_node; jnode++) { stk::mesh::Entity node_j = * elem_nodes[ jnode ].entity(); double* coord_data_j = stk::percept::PerceptMesh::field_data(coordField, node_j); double dot_0 = plane_dot_product(plane_point, plane_normal, coord_data_i); double dot_1 = plane_dot_product(plane_point, plane_normal, coord_data_j); // if edge crosses the plane... if(dot_0 * dot_1 < 0) { found = true; break; } } } if(found) { f_data[0] = 1.0; // std::cout << "Splitting: " << element.identifier() << std::endl; } else { f_data[0] = 0.0; // std::cout << "Not splitting: " << element.identifier() << std::endl; } return false; // don't terminate the loop }
/// modeled after code from Mesquite::IdealWeightMeanRatio::evaluate() bool JacobianUtil::operator()(double& m, PerceptMesh& eMesh, stk::mesh::Entity& element, stk::mesh::FieldBase *coord_field, const CellTopologyData * topology_data ) { MsqError err; static MsqMatrix<3,3> J; static Vector3D n; // Surface normal for 2D objects // Prism and Hex element descriptions static const int locs_prism[6][4] = {{0, 1, 2, 3}, {1, 2, 0, 4}, {2, 0, 1, 5}, {3, 5, 4, 0}, {4, 3, 5, 1}, {5, 4, 3, 2}}; static const int locs_hex[8][4] = {{0, 1, 3, 4}, {1, 2, 0, 5}, {2, 3, 1, 6}, {3, 0, 2, 7}, {4, 7, 5, 0}, {5, 4, 6, 1}, {6, 5, 7, 2}, {7, 6, 4, 3}}; int i=0; static const Vector3D d_con(1.0, 1.0, 1.0); bool metric_valid = false; if (!topology_data) topology_data = stk::percept::PerceptMesh::get_cell_topology(element); stk::mesh::PairIterRelation v_i = element.relations(eMesh.node_rank()); m_num_nodes = v_i.size(); //#define VERTEX_2D(vi) vector_2D( eMesh.field_data(coord_field, *vi.entity() ) ) //#define VERTEX_3D(vi) vector_3D( eMesh.field_data(coord_field, *vi.entity() ) ) #define VERTEX_2D(vi) vector_2D( stk::mesh::field_data( *static_cast<const VectorFieldType *>(coord_field) , *vi.entity() ) ) #define VERTEX_3D(vi) vector_3D( stk::mesh::field_data( *static_cast<const VectorFieldType *>(coord_field) , *vi.entity() ) ) switch(topology_data->key) { case shards::Triangle<3>::key: n[0] = 0; n[1] = 0; n[2] = 1; mCoords[0] = VERTEX_2D(v_i[0]); mCoords[1] = VERTEX_2D(v_i[1]); mCoords[2] = VERTEX_2D(v_i[2]); metric_valid = jacobian_matrix_2D(m, J, mCoords, n, d_con); for (i = 0; i < 4; i++) { m_detJ[i] = m; m_J[i] = J; } break; case shards::Quadrilateral<4>::key: n[0] = 0; n[1] = 0; n[2] = 1; for (i = 0; i < 4; ++i) { mCoords[0] = VERTEX_2D(v_i[locs_hex[i][0]]); mCoords[1] = VERTEX_2D(v_i[locs_hex[i][1]]); mCoords[2] = VERTEX_2D(v_i[locs_hex[i][2]]); metric_valid = jacobian_matrix_2D(m_detJ[i], m_J[i], mCoords, n, d_con); } m = average_metrics(m_detJ, 4, err); MSQ_ERRZERO(err); break; case shards::Tetrahedron<4>::key: mCoords[0] = VERTEX_3D(v_i[0]); mCoords[1] = VERTEX_3D(v_i[1]); mCoords[2] = VERTEX_3D(v_i[2]); mCoords[3] = VERTEX_3D(v_i[3]); metric_valid = jacobian_matrix_3D(m, J, mCoords, n, d_con); for (i = 0; i < 4; i++) { m_detJ[i] = m; m_J[i] = J; } break; case shards::Pyramid<5>::key: for (i = 0; i < 4; ++i) { mCoords[0] = VERTEX_3D(v_i[ i ]); mCoords[1] = VERTEX_3D(v_i[(i+1)%4]); mCoords[2] = VERTEX_3D(v_i[(i+3)%4]); mCoords[3] = VERTEX_3D(v_i[ 4 ]); metric_valid = jacobian_matrix_3D(m_detJ[i], m_J[i], mCoords, n, d_con); } // FIXME m_J[4] = (m_J[0]+m_J[1]+m_J[2]+m_J[3]); m_J[4] *= 0.25; m_detJ[4] = det(m_J[4]); m = average_metrics(m_detJ, 5, err); MSQ_ERRZERO(err); break; case shards::Wedge<6>::key: for (i = 0; i < 6; ++i) { mCoords[0] = VERTEX_3D(v_i[locs_prism[i][0]]); mCoords[1] = VERTEX_3D(v_i[locs_prism[i][1]]); mCoords[2] = VERTEX_3D(v_i[locs_prism[i][2]]); mCoords[3] = VERTEX_3D(v_i[locs_prism[i][3]]); metric_valid = jacobian_matrix_3D(m_detJ[i], m_J[i], mCoords, n, d_con); } m = average_metrics(m_detJ, 6, err); MSQ_ERRZERO(err); break; case shards::Hexahedron<8>::key: for (i = 0; i < 8; ++i) { mCoords[0] = VERTEX_3D(v_i[locs_hex[i][0]]); mCoords[1] = VERTEX_3D(v_i[locs_hex[i][1]]); mCoords[2] = VERTEX_3D(v_i[locs_hex[i][2]]); mCoords[3] = VERTEX_3D(v_i[locs_hex[i][3]]); metric_valid = jacobian_matrix_3D(m_detJ[i], m_J[i], mCoords, n, d_con); } m = average_metrics(m_detJ, 8, err); MSQ_ERRZERO(err); break; // unimplemented case shards::Node::key: case shards::Particle::key: case shards::Line<2>::key: case shards::Line<3>::key: case shards::ShellLine<2>::key: case shards::ShellLine<3>::key: case shards::Beam<2>::key: case shards::Beam<3>::key: case shards::Triangle<4>::key: case shards::Triangle<6>::key: case shards::ShellTriangle<3>::key: case shards::ShellTriangle<6>::key: case shards::Quadrilateral<8>::key: case shards::Quadrilateral<9>::key: case shards::ShellQuadrilateral<4>::key: case shards::ShellQuadrilateral<8>::key: case shards::ShellQuadrilateral<9>::key: case shards::Tetrahedron<8>::key: case shards::Tetrahedron<10>::key: case shards::Tetrahedron<11>::key: case shards::Hexahedron<20>::key: case shards::Hexahedron<27>::key: case shards::Pyramid<13>::key: case shards::Pyramid<14>::key: case shards::Wedge<15>::key: case shards::Wedge<18>::key: case shards::Pentagon<5>::key: case shards::Hexagon<6>::key: default: shards::CellTopology topology(topology_data); std::cout << "topology = " << topology.getName() << std::endl; throw std::runtime_error("unknown/unhandled topology in JacobianUtil"); break; } // end switch over element type return metric_valid; }
void createNewElements(percept::PerceptMesh& eMesh, NodeRegistry& nodeRegistry, stk::mesh::Entity& element, NewSubEntityNodesType& new_sub_entity_nodes, vector<stk::mesh::Entity *>::iterator& element_pool, stk::mesh::FieldBase *proc_rank_field=0) { const CellTopologyData * const cell_topo_data = stk::percept::PerceptMesh::get_cell_topology(element); typedef boost::tuple<stk::mesh::EntityId, stk::mesh::EntityId> line_tuple_type; static vector<line_tuple_type> elems(2); CellTopology cell_topo(cell_topo_data); const stk::mesh::PairIterRelation elem_nodes = element.relations(stk::mesh::fem::FEMMetaData::NODE_RANK); std::vector<stk::mesh::Part*> add_parts; std::vector<stk::mesh::Part*> remove_parts; add_parts = m_toParts; unsigned num_nodes_on_edge = new_sub_entity_nodes[m_eMesh.edge_rank()][0].size(); if (!num_nodes_on_edge) return; double coord_x[3]; for (int iedge = 0; iedge < 1; iedge++) { //double * mp = midPoint(EDGE_COORD(iedge,0), EDGE_COORD(iedge,1), eMesh.get_spatial_dim(), coord_x); //double * mp = midPoint(FACE_COORD(iedge,0), FACE_COORD(iedge,1), eMesh.get_spatial_dim(), coord_x); double * mp = midPoint(VERT_COORD(0), VERT_COORD(1), eMesh.get_spatial_dim(), coord_x); if (!EDGE_N(iedge)) { std::cout << "P[" << eMesh.get_rank() << " nid ## = 0 " << std::endl; } eMesh.createOrGetNode(EDGE_N(iedge), mp); } // FIXME nodeRegistry.makeCentroidCoords(*const_cast<stk::mesh::Entity *>(&element), m_primaryEntityRank, 0u); nodeRegistry.addToExistingParts(*const_cast<stk::mesh::Entity *>(&element), m_primaryEntityRank, 0u); nodeRegistry.interpolateFields(*const_cast<stk::mesh::Entity *>(&element), m_primaryEntityRank, 0u); Elem::CellTopology elem_celltopo = Elem::getCellTopology< FromTopology >(); const Elem::RefinementTopology* ref_topo_p = Elem::getRefinementTopology(elem_celltopo); const Elem::RefinementTopology& ref_topo = *ref_topo_p; #ifndef NDEBUG unsigned num_child = ref_topo.num_child(); VERIFY_OP(num_child, == , 2, "createNewElements num_child problem"); bool homogeneous_child = ref_topo.homogeneous_child(); VERIFY_OP(homogeneous_child, ==, true, "createNewElements homogeneous_child"); #endif // new_sub_entity_nodes[i][j] //const UInt * const * child_nodes() const { //const UInt * child_node_0 = ref_topo.child_node(0); typedef Elem::StdMeshObjTopologies::RefTopoX RefTopoX; RefTopoX& l2 = Elem::StdMeshObjTopologies::RefinementTopologyExtra< FromTopology > ::refinement_topology; #define CENTROID_N NN(m_primaryEntityRank,0) for (unsigned iChild = 0; iChild < 2; iChild++) { unsigned EN[2]; for (unsigned jNode = 0; jNode < 2; jNode++) { unsigned childNodeIdx = ref_topo.child_node(iChild)[jNode]; #ifndef NDEBUG unsigned childNodeIdxCheck = l2[childNodeIdx].ordinal_of_node; VERIFY_OP(childNodeIdx, ==, childNodeIdxCheck, "childNodeIdxCheck"); #endif unsigned inode=0; if (l2[childNodeIdx].rank_of_subcell == 0) inode = VERT_N(l2[childNodeIdx].ordinal_of_subcell); else if (l2[childNodeIdx].rank_of_subcell == 1) inode = EDGE_N(l2[childNodeIdx].ordinal_of_subcell); // else if (l2[childNodeIdx].rank_of_subcell == 2) // inode = CENTROID_N; EN[jNode] = inode; } elems[iChild] = line_tuple_type(EN[0], EN[1]); } #undef CENTROID_N for (unsigned ielem=0; ielem < elems.size(); ielem++) { stk::mesh::Entity& newElement = *(*element_pool); #if 0 if (proc_rank_field && proc_rank_field->rank() == m_eMesh.edge_rank()) //&& m_eMesh.get_spatial_dim()==1) { double *fdata = stk::mesh::field_data( *static_cast<const ScalarFieldType *>(proc_rank_field) , newElement ); //fdata[0] = double(m_eMesh.get_rank()); fdata[0] = double(newElement.owner_rank()); } #endif stk::mesh::FieldBase * proc_rank_field_edge = m_eMesh.get_field("proc_rank_edge"); if (proc_rank_field_edge) { double *fdata = stk::mesh::field_data( *static_cast<const ScalarFieldType *>(proc_rank_field_edge) , newElement ); fdata[0] = double(newElement.owner_rank()); //fdata[0] = 1234.56; if (0) std::cout << "P[" << m_eMesh.get_rank() << "] tmp set proc_rank_field_edge to value = " << newElement.owner_rank() << " for side element = " << newElement.identifier() << std::endl; } //eMesh.get_bulk_data()->change_entity_parts( newElement, add_parts, remove_parts ); change_entity_parts(eMesh, element, newElement); { if (!elems[ielem].get<0>()) { std::cout << "P[" << eMesh.get_rank() << " nid = 0 " << std::endl; exit(1); } } eMesh.get_bulk_data()->declare_relation(newElement, eMesh.createOrGetNode(elems[ielem].get<0>()), 0); eMesh.get_bulk_data()->declare_relation(newElement, eMesh.createOrGetNode(elems[ielem].get<1>()), 1); set_parent_child_relations(eMesh, element, newElement, ielem); element_pool++; } }
//---------------------------------------------------------------------------- // // Stress fracture criterion function. // bool StressFracture::computeFractureCriterion(stk::mesh::Entity entity, double p) { // Fracture only defined on the boundary of the elements stk::mesh::EntityRank rank = entity.entity_rank(); assert(rank == num_dim_ - 1); stk::mesh::PairIterRelation neighbor_elems = entity.relations(element_rank_); // Need an element on each side of the edge if(neighbor_elems.size() != 2) return false; // Note that these are element GIDs stk::mesh::EntityId elem_0_Id = neighbor_elems[0].entity()->identifier(); stk::mesh::EntityId elem_1_Id = neighbor_elems[1].entity()->identifier(); Albany::WsLIDList& elemGIDws = stk_.getElemGIDws(); // Have two elements, one on each size of the edge (or // face). Check and see if the stresses are such that we want to // split the mesh here. // // Initial hack - GAH: if the average stress between two elements // is above the input value "Fracture Stress", split them at the // edge bool is_open = false; // Check criterion // If average between cells is above crit, split // if (0.5 * (avg_stresses[elemGIDws[elem_0_Id].ws][elemGIDws[elem_0_Id].LID] + // avg_stresses[elemGIDws[elem_1_Id].ws][elemGIDws[elem_1_Id].LID]) >= crit_stress){ // If stress difference across face it above crit, split // if (fabs(avg_stresses[elemGIDws[elem_0_Id].ws][elemGIDws[elem_0_Id].LID] - // avg_stresses[elemGIDws[elem_1_Id].ws][elemGIDws[elem_1_Id].LID]) >= crit_stress){ // Just split the doggone elements already!!! if(p == 5) { if((elem_0_Id - 1 == 35 && elem_1_Id - 1 == 140) || (elem_1_Id - 1 == 35 && elem_0_Id - 1 == 140)) { is_open = true; std::cout << "Splitting elements " << elem_0_Id - 1 << " and " << elem_1_Id - 1 << std::endl; //std::cout << avg_stresses[elemGIDws[elem_0_Id].ws][elemGIDws[elem_0_Id].LID] << " " << // avg_stresses[elemGIDws[elem_1_Id].ws][elemGIDws[elem_1_Id].LID] << std::endl; } } else if(p == 10) { if((elem_0_Id - 1 == 42 && elem_1_Id - 1 == 147) || (elem_1_Id - 1 == 42 && elem_0_Id - 1 == 147)) { is_open = true; std::cout << "Splitting elements " << elem_0_Id - 1 << " and " << elem_1_Id - 1 << std::endl; } } else if(p == 15) { if((elem_0_Id - 1 == 49 && elem_1_Id - 1 == 154) || (elem_1_Id - 1 == 49 && elem_0_Id - 1 == 154)) { is_open = true; std::cout << "Splitting elements " << elem_0_Id - 1 << " and " << elem_1_Id - 1 << std::endl; } } return is_open; }
void IEdgeAdapter:: refineMethodApply(NodeRegistry::ElementFunctionPrototype function, const stk::mesh::Entity& element, vector<NeededEntityType>& needed_entity_ranks) { const CellTopologyData * const cell_topo_data = stk::percept::PerceptMesh::get_cell_topology(element); CellTopology cell_topo(cell_topo_data); const mesh::PairIterRelation elem_nodes = element.relations(stk::mesh::fem::FEMMetaData::NODE_RANK); VectorFieldType* coordField = m_eMesh.get_coordinates_field(); for (unsigned ineed_ent=0; ineed_ent < needed_entity_ranks.size(); ineed_ent++) { unsigned numSubDimNeededEntities = 0; stk::mesh::EntityRank needed_entity_rank = needed_entity_ranks[ineed_ent].first; if (needed_entity_rank == m_eMesh.edge_rank()) { numSubDimNeededEntities = cell_topo_data->edge_count; } else if (needed_entity_rank == m_eMesh.face_rank()) { numSubDimNeededEntities = cell_topo_data->side_count; throw std::runtime_error("IEdgeAdapter::apply can't use IEdgeAdapter for RefinerPatterns that require face nodes"); } else if (needed_entity_rank == m_eMesh.element_rank()) { numSubDimNeededEntities = 1; throw std::runtime_error("IEdgeAdapter::apply can't use IEdgeAdapter for RefinerPatterns that require volume nodes"); } // see how many edges are already marked int num_marked=0; std::vector<int> edge_marks(numSubDimNeededEntities,0); if (needed_entity_rank == m_eMesh.edge_rank()) { for (unsigned iSubDimOrd = 0; iSubDimOrd < numSubDimNeededEntities; iSubDimOrd++) { bool is_empty = m_nodeRegistry->is_empty( element, needed_entity_rank, iSubDimOrd); if (!is_empty) { edge_marks[iSubDimOrd] = 1; ++num_marked; } } } for (unsigned iSubDimOrd = 0; iSubDimOrd < numSubDimNeededEntities; iSubDimOrd++) { if (needed_entity_rank == m_eMesh.edge_rank()) { stk::mesh::Entity & node0 = *elem_nodes[cell_topo_data->edge[iSubDimOrd].node[0]].entity(); stk::mesh::Entity & node1 = *elem_nodes[cell_topo_data->edge[iSubDimOrd].node[1]].entity(); double * const coord0 = stk::mesh::field_data( *coordField , node0 ); double * const coord1 = stk::mesh::field_data( *coordField , node1 ); int markInfo = mark(element, iSubDimOrd, node0, node1, coord0, coord1, &edge_marks); bool needNodes = (DO_REFINE & markInfo); { (m_nodeRegistry ->* function)(element, needed_entity_ranks[ineed_ent], iSubDimOrd, needNodes); } } } // iSubDimOrd } // ineed_ent }
bool helperSubDim(const stk::mesh::Entity& child_element, stk::mesh::FieldBase *field, const mesh::BulkData& bulkData) { EXCEPTWATCH; const CellTopologyData * const child_cell_topo_data = stk::percept::PerceptMesh::get_cell_topology(child_element); CellTopology child_cell_topo(child_cell_topo_data); int child_cell_dimension = child_cell_topo.getDimension(); int meta_dimension = mesh::fem::FEMMetaData::get_meta_data(mesh::fem::FEMMetaData::get(bulkData)).get_spatial_dimension(); // for now, only allow face (or edge) VERIFY_OP_ON(child_cell_dimension, ==, meta_dimension - 1, "Dimensions don't match"); VectorFieldType& coord_field = *(mesh::fem::FEMMetaData::get(bulkData)).get_field<VectorFieldType>("coordinates"); // FIXME for fields not on a Node unsigned nDOF = m_nDOFs; unsigned nCells = PerceptMesh::size1(child_element); m_count_elems += nCells; typedef IntrepidManager IM; unsigned cubDegree = m_cubDegree; const stk::mesh::PairIterRelation parent_elements = child_element.relations(child_element.entity_rank() + 1); VERIFY_OP_ON(parent_elements.size(), ==, 1, "cant find parent"); const stk::mesh::Entity& element = *parent_elements[0].entity(); unsigned i_face = parent_elements[0].identifier(); const CellTopologyData * const cell_topo_data = stk::percept::PerceptMesh::get_cell_topology(element); CellTopology cell_topo(cell_topo_data); int cell_dimension = cell_topo.getDimension(); VERIFY_OP_ON(cell_dimension, ==, meta_dimension , "Dimensions don't match"); IM im(Elements_Tag(nCells), cell_topo, cubDegree); IM imChild(Elements_Tag(nCells), child_cell_topo, cubDegree); unsigned numCubPoints_child = imChild.m_cub->getNumPoints(); im.m_Cub_Points_Tag = Cub_Points_Tag(numCubPoints_child); if (0) { std::cout << "numCubPoints_child= " << numCubPoints_child << " parent rank= " << element.entity_rank() << " parent topo= " << cell_topo.getName() << std::endl; } // FIXME im.m_DOFs_Tag.num = m_nDOFs; // FIXME // _c suffix is for the child (face) element IM::Jacobian J (im); IM::FaceNormal fn (im); //IM::JacobianDet dJ (im); IM::CubaturePoints xi (im); IM::CubaturePoints xi_c (imChild); IM::CellWorkSet cn (im); IM::CubatureWeights wt (im); IM::CubatureWeights wt_c (imChild); IM::PhysicalCoords pc (im); IM::IntegrandValues iv (im); IM::IntegrandValuesDOF ivD (im); IM::Integral Io (im); IM::Bases Nb (im); IM::WeightedMeasure wXfn (im); IM::FieldValues fv (im); imChild.m_cub->getCubature(xi_c, wt_c); unsigned spaceDim = im.m_Spatial_Dim_Tag.num; PerceptMesh::fillCellNodes(element, &coord_field, cn, spaceDim); // get parent cell integration points // Map Gauss points on quad to reference face: paramGaussPoints -> refGaussPoints CellTools<double>::mapToReferenceSubcell(xi, xi_c, 2, i_face, cell_topo); // FIXME magic // get jacobian J(xi, cn, cell_topo); //dJ(J); //shards::ArrayVector<double, shards::NaturalOrder, Elements_Tag, Cub_Points_Tag > fn_Norm; // FIXME //fn(J, i_face, cell_topo); MDArray J_mda; J.copyTo(J_mda); MDArray fn_mda(im.m_Elements_Tag.num, numCubPoints_child, spaceDim); CellTools<double>::getPhysicalFaceNormals(fn_mda, J_mda, i_face, cell_topo); /// get norm of fn for (int icell = 0; icell < im.m_Elements_Tag.num; icell++) { for (int ipt = 0; ipt < (int)numCubPoints_child; ipt++) { double sum = 0.0; for (int i = 0; i < (int)spaceDim; i++) { sum += square(fn_mda(icell, ipt, i)); } wXfn(icell, ipt) = std::sqrt(sum) * wt_c(ipt); } } if (0) { using namespace shards; //std::cout << "dJ= \n" << dJ << std::endl; std::cout << "wXfn= \n" << wXfn << std::endl; std::cout << "xi= \n" << xi << std::endl; std::cout << "wt= \n" << wt << std::endl; std::cout << "cn= \n" << cn << std::endl; Util::setDoPause(true); Util::pause(true); } // get physical coordinates at integration points pc(cn, xi); // get bases #if 1 // FIXME MDArray xi_mda; xi.copyTo(xi_mda); Nb(element, xi_mda); #else Nb(element, xi); #endif // apply integrand (right now we have MDArray hard-coded... FIXME - templatize on its type) // it should look like this (one instead of multiple lines): #if 0 m_integrand(pc, v); #else MDArray pc_mda; pc.copyTo(pc_mda); std::vector<int> ivDims; ivD.dimensions( ivDims); /// NOTE: m_integrand requires the ranks of in/out MDArrays to be such that out_rank >= in_rank /// Thus, we use IntegrandValuesDOF with [DOF] = 1, and then copy the result to IntegrandValues /// which does not have the additional rightmost DOF index (Intrepid doesn't have the concept of /// DOF's, it works on scalars only for the integration routines, or at least that's how I understand /// it currently. // create an array that stk::percept::Function will like to hold the results ivDims[ivDims.size()-1] = m_nDOFs; MDArray iv_mda ( Teuchos::Array<int>(ivDims.begin(), ivDims.end())); if (m_turboOpt == TURBO_ELEMENT || m_turboOpt == TURBO_BUCKET) { m_integrand(pc_mda, iv_mda, element, xi_mda); } else { m_integrand(pc_mda, iv_mda); } // now, copy from the results to an array that Intrepid::integrate will like #endif for (unsigned iDof = 0; iDof < nDOF; iDof++) { iv.copyFrom(im, iv_mda, iDof); // get the integral if (m_accumulation_type == ACCUMULATE_SUM) { Io(iv, wXfn, COMP_BLAS); } //optional design: // // Io(integrand(pc_mda, v), wXdJ(w, dJ(J(xi, c, cell_topo)), COMP_BLAS); for (unsigned iCell = 0; iCell < nCells; iCell++) { // if (Util::getFlag(0)) // { // std::cout << "tmp Io(iCell)= " << Io(iCell) << std::endl; // Util::pause(true, "Io(iCell)"); // } if (m_accumulation_type == ACCUMULATE_SUM) { m_accumulation_buffer[iDof] += Io(iCell); } else if (m_accumulation_type == ACCUMULATE_MAX) { double valIo = 0.0; for (int ivpts = 0; ivpts < iv.dimension(1); ivpts++) { valIo = std::max(valIo, iv((int)iCell, ivpts)); } //std::cout << "m_accumulation_buffer[iDof] = " << m_accumulation_buffer[iDof] << " valIO= " << valIo << std::endl; m_accumulation_buffer[iDof] = std::max(m_accumulation_buffer[iDof], valIo); } } } return false; }
void TestLocalRefinerTri2:: refineMethodApply(NodeRegistry::ElementFunctionPrototype function, const stk::mesh::Entity& element, vector<NeededEntityType>& needed_entity_ranks) { const CellTopologyData * const cell_topo_data = stk::percept::PerceptMesh::get_cell_topology(element); CellTopology cell_topo(cell_topo_data); const mesh::PairIterRelation elem_nodes = element.relations(stk::mesh::fem::FEMMetaData::NODE_RANK); VectorFieldType* coordField = m_eMesh.get_coordinates_field(); for (unsigned ineed_ent=0; ineed_ent < needed_entity_ranks.size(); ineed_ent++) { unsigned numSubDimNeededEntities = 0; stk::mesh::EntityRank needed_entity_rank = needed_entity_ranks[ineed_ent].first; if (needed_entity_rank == m_eMesh.edge_rank()) { numSubDimNeededEntities = cell_topo_data->edge_count; } else if (needed_entity_rank == m_eMesh.face_rank()) { numSubDimNeededEntities = cell_topo_data->side_count; } else if (needed_entity_rank == m_eMesh.element_rank()) { numSubDimNeededEntities = 1; } // see how many edges are already marked int num_marked=0; if (needed_entity_rank == m_eMesh.edge_rank()) { for (unsigned iSubDimOrd = 0; iSubDimOrd < numSubDimNeededEntities; iSubDimOrd++) { bool is_empty = m_nodeRegistry->is_empty( element, needed_entity_rank, iSubDimOrd); if (!is_empty) ++num_marked; } } for (unsigned iSubDimOrd = 0; iSubDimOrd < numSubDimNeededEntities; iSubDimOrd++) { /// note: at this level of granularity we can do single edge refinement, hanging nodes, etc. //SubDimCell_SDSEntityType subDimEntity; //getSubDimEntity(subDimEntity, element, needed_entity_rank, iSubDimOrd); //bool is_empty = m_nodeRegistry->is_empty( element, needed_entity_rank, iSubDimOrd); //if(1||!is_empty) if (needed_entity_rank == m_eMesh.edge_rank()) { stk::mesh::Entity & node0 = *elem_nodes[cell_topo_data->edge[iSubDimOrd].node[0]].entity(); stk::mesh::Entity & node1 = *elem_nodes[cell_topo_data->edge[iSubDimOrd].node[1]].entity(); double * const coord0 = stk::mesh::field_data( *coordField , node0 ); double * const coord1 = stk::mesh::field_data( *coordField , node1 ); // only refine diagonals of the split quads if (m_diagonals) { if ( std::abs(coord0[0]-coord1[0]) > 1.e-3 && std::abs(coord0[1]-coord1[1]) > 1.e-3 ) { (m_nodeRegistry ->* function)(element, needed_entity_ranks[ineed_ent], iSubDimOrd, true); } } else { if ( std::abs(coord0[0]-coord1[0]) < 1.e-3 && std::abs(coord0[1]-coord1[1]) > 1.e-3 ) { (m_nodeRegistry ->* function)(element, needed_entity_ranks[ineed_ent], iSubDimOrd, true); } } } } // iSubDimOrd } // ineed_ent }
unsigned Albany::STKDiscretization::determine_local_side_id( const stk::mesh::Entity & elem , stk::mesh::Entity & side ) { using namespace stk; const CellTopologyData * const elem_top = mesh::fem::get_cell_topology( elem ).getCellTopologyData(); const mesh::PairIterRelation elem_nodes = elem.relations( mesh::fem::FEMMetaData::NODE_RANK ); const mesh::PairIterRelation side_nodes = side.relations( mesh::fem::FEMMetaData::NODE_RANK ); int side_id = -1 ; if(elem_nodes.size() == 0 || side_nodes.size() == 0){ // Node relations are not present, look at elem->face int elem_rank = elem.entity_rank(); const mesh::PairIterRelation elem_sides = elem.relations( elem_rank - 1); for ( unsigned i = 0 ; i < elem_sides.size() ; ++i ) { const stk::mesh::Entity & elem_side = *elem_sides[i].entity(); if(elem_side.identifier() == side.identifier()){ // Found the local side in the element side_id = static_cast<int>(i); return side_id; } } if ( side_id < 0 ) { std::ostringstream msg ; msg << "determine_local_side_id( " ; msg << elem_top->name ; msg << " , Element[ " ; msg << elem.identifier(); msg << " ]{" ; for ( unsigned i = 0 ; i < elem_sides.size() ; ++i ) { msg << " " << elem_sides[i].entity()->identifier(); } msg << " } , Side[ " ; msg << side.identifier(); msg << " ] ) FAILED" ; throw std::runtime_error( msg.str() ); } } else { // Conventional elem->node - side->node connectivity present for ( unsigned i = 0 ; side_id == -1 && i < elem_top->side_count ; ++i ) { const CellTopologyData & side_top = * elem_top->side[i].topology ; const unsigned * side_map = elem_top->side[i].node ; if ( side_nodes.size() == side_top.node_count ) { side_id = i ; for ( unsigned j = 0 ; side_id == static_cast<int>(i) && j < side_top.node_count ; ++j ) { mesh::Entity * const elem_node = elem_nodes[ side_map[j] ].entity(); bool found = false ; for ( unsigned k = 0 ; ! found && k < side_top.node_count ; ++k ) { found = elem_node == side_nodes[k].entity(); } if ( ! found ) { side_id = -1 ; } } } } if ( side_id < 0 ) { std::ostringstream msg ; msg << "determine_local_side_id( " ; msg << elem_top->name ; msg << " , Element[ " ; msg << elem.identifier(); msg << " ]{" ; for ( unsigned i = 0 ; i < elem_nodes.size() ; ++i ) { msg << " " << elem_nodes[i].entity()->identifier(); } msg << " } , Side[ " ; msg << side.identifier(); msg << " ]{" ; for ( unsigned i = 0 ; i < side_nodes.size() ; ++i ) { msg << " " << side_nodes[i].entity()->identifier(); } msg << " } ) FAILED" ; throw std::runtime_error( msg.str() ); } } return static_cast<unsigned>(side_id) ; }
void TestLocalRefinerTet_N_2_1:: refineMethodApply(NodeRegistry::ElementFunctionPrototype function, const stk::mesh::Entity& element, vector<NeededEntityType>& needed_entity_ranks) { //static int n_seq = 400; const CellTopologyData * const cell_topo_data = stk::percept::PerceptMesh::get_cell_topology(element); CellTopology cell_topo(cell_topo_data); const mesh::PairIterRelation elem_nodes = element.relations(stk::mesh::fem::FEMMetaData::NODE_RANK); //VectorFieldType* coordField = m_eMesh.get_coordinates_field(); for (unsigned ineed_ent=0; ineed_ent < needed_entity_ranks.size(); ineed_ent++) { unsigned numSubDimNeededEntities = 0; stk::mesh::EntityRank needed_entity_rank = needed_entity_ranks[ineed_ent].first; if (needed_entity_rank == m_eMesh.edge_rank()) { numSubDimNeededEntities = cell_topo_data->edge_count; } else if (needed_entity_rank == m_eMesh.face_rank()) { numSubDimNeededEntities = cell_topo_data->side_count; } else if (needed_entity_rank == m_eMesh.element_rank()) { numSubDimNeededEntities = 1; } // see how many edges are already marked int num_marked=0; if (needed_entity_rank == m_eMesh.edge_rank()) { for (unsigned iSubDimOrd = 0; iSubDimOrd < numSubDimNeededEntities; iSubDimOrd++) { bool is_empty = m_nodeRegistry->is_empty( element, needed_entity_rank, iSubDimOrd); if (!is_empty) ++num_marked; } } for (unsigned iSubDimOrd = 0; iSubDimOrd < numSubDimNeededEntities; iSubDimOrd++) { /// note: at this level of granularity we can do single edge refinement, hanging nodes, etc. //SubDimCell_SDSEntityType subDimEntity; //getSubDimEntity(subDimEntity, element, needed_entity_rank, iSubDimOrd); //bool is_empty = m_nodeRegistry->is_empty( element, needed_entity_rank, iSubDimOrd); //if(1||!is_empty) if (needed_entity_rank == m_eMesh.edge_rank()) { #if 0 stk::mesh::Entity & node0 = *elem_nodes[cell_topo_data->edge[iSubDimOrd].node[0]].entity(); stk::mesh::Entity & node1 = *elem_nodes[cell_topo_data->edge[iSubDimOrd].node[1]].entity(); double * const coord0 = stk::mesh::field_data( *coordField , node0 ); double * const coord1 = stk::mesh::field_data( *coordField , node1 ); // vertical line position const double vx = 0.21; // horizontal line position const double vy = 1.21; // choose to refine or not if ( ( std::fabs(coord0[0]-coord1[0]) > 1.e-3 && ( (coord0[0] < vx && vx < coord1[0]) || (coord1[0] < vx && vx < coord0[0]) ) ) || ( std::fabs(coord0[1]-coord1[1]) > 1.e-3 && ( (coord0[1] < vy && vy < coord1[1]) || (coord1[1] < vy && vy < coord0[1]) ) ) ) { (m_nodeRegistry ->* function)(element, needed_entity_ranks[ineed_ent], iSubDimOrd, true); } #endif // mark first m_edge_mark_bitcode edges std::cout << "tmp TestLocalRefinerTet_N_2_1 element.identifier() = " << element.identifier() << " m_edge_mark_bitcode= " << m_edge_mark_bitcode << std::endl; if ( ((1 << iSubDimOrd) & m_edge_mark_bitcode) && element.identifier() == 1) (m_nodeRegistry ->* function)(element, needed_entity_ranks[ineed_ent], iSubDimOrd, true); } } // iSubDimOrd } // ineed_ent }
void createNewElements(percept::PerceptMesh& eMesh, NodeRegistry& nodeRegistry, stk::mesh::Entity& element, NewSubEntityNodesType& new_sub_entity_nodes, vector<stk::mesh::Entity *>::iterator& element_pool, stk::mesh::FieldBase *proc_rank_field=0) { const CellTopologyData * const cell_topo_data = stk::percept::PerceptMesh::get_cell_topology(element); typedef boost::tuple<stk::mesh::EntityId, stk::mesh::EntityId, stk::mesh::EntityId, stk::mesh::EntityId> quad_tuple_type; static vector<quad_tuple_type> elems(4); CellTopology cell_topo(cell_topo_data); const stk::mesh::PairIterRelation elem_nodes = element.relations(stk::mesh::fem::FEMMetaData::NODE_RANK); //stk::mesh::Part & active = mesh->ActivePart(); //stk::mesh::Part & quad4 = mesh->QuadPart(); std::vector<stk::mesh::Part*> add_parts; std::vector<stk::mesh::Part*> remove_parts; //add_parts.push_back( &active ); //FIXME //add_parts.push_back( const_cast<mesh::Part*>( eMesh.getPart(m_toTopoPartName) )); add_parts = m_toParts; double tmp_x[3]; for (int iedge = 0; iedge < 4; iedge++) { double * mp = midPoint(EDGE_COORD(iedge,0), EDGE_COORD(iedge,1), eMesh.get_spatial_dim(), tmp_x); if (!EDGE_N(iedge)) { std::cout << "P[" << eMesh.get_rank() << " nid ## = 0 << " << std::endl; } eMesh.createOrGetNode(EDGE_N(iedge), mp); } nodeRegistry.makeCentroidCoords(*const_cast<stk::mesh::Entity *>(&element), m_eMesh.element_rank(), 0u); // new_sub_entity_nodes[i][j] #define CENTROID_N NN(m_primaryEntityRank,0) elems[0] = quad_tuple_type(VERT_N(0), EDGE_N(0), CENTROID_N, EDGE_N(3)); elems[1] = quad_tuple_type(VERT_N(1), EDGE_N(1), CENTROID_N, EDGE_N(0)); elems[2] = quad_tuple_type(VERT_N(2), EDGE_N(2), CENTROID_N, EDGE_N(1)); elems[3] = quad_tuple_type(VERT_N(3), EDGE_N(3), CENTROID_N, EDGE_N(2)); #undef CENTROID_N // write a diagram of the refinement pattern as a vtk file, or a latex/tikz/pgf file #define WRITE_DIAGRAM 0 #if WRITE_DIAGRAM #endif for (unsigned ielem=0; ielem < elems.size(); ielem++) { stk::mesh::Entity& newElement = *(*element_pool); if (proc_rank_field) { double *fdata = stk::mesh::field_data( *static_cast<const ScalarFieldType *>(proc_rank_field) , newElement ); //fdata[0] = double(m_eMesh.get_rank()); fdata[0] = double(newElement.owner_rank()); } eMesh.get_bulk_data()->change_entity_parts( newElement, add_parts, remove_parts ); { if (!elems[ielem].get<0>()) { std::cout << "P[" << eMesh.get_rank() << " nid = 0 << " << std::endl; exit(1); } } eMesh.get_bulk_data()->declare_relation(newElement, eMesh.createOrGetNode(elems[ielem].get<0>()), 0); eMesh.get_bulk_data()->declare_relation(newElement, eMesh.createOrGetNode(elems[ielem].get<1>()), 1); eMesh.get_bulk_data()->declare_relation(newElement, eMesh.createOrGetNode(elems[ielem].get<2>()), 2); eMesh.get_bulk_data()->declare_relation(newElement, eMesh.createOrGetNode(elems[ielem].get<3>()), 3); set_parent_child_relations(eMesh, element, newElement, ielem); element_pool++; } }