//---------------------------------------------------------------------------- // // 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; }
//---------------------------------------------------------------------------- // // 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; }
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; }
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) ; }