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
}
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
}
예제 #3
0
      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;
      }
예제 #4
0
void Albany::STKDiscretization::computeSideSets(){

  // Clean up existing sideset structure if remeshing

  for(int i = 0; i < sideSets.size(); i++)
    sideSets[i].clear(); // empty the ith map

  const stk::mesh::EntityRank element_rank = metaData.element_rank();

  // iterator over all side_rank parts found in the mesh
  std::map<std::string, stk::mesh::Part*>::iterator ss = stkMeshStruct->ssPartVec.begin();

  int numBuckets = wsEBNames.size();

  sideSets.resize(numBuckets); // Need a sideset list per workset

  while ( ss != stkMeshStruct->ssPartVec.end() ) {

    // Get all owned sides in this side set
    stk::mesh::Selector select_owned_in_sspart =

      // get only entities in the ss part (ss->second is the current sideset part)
      stk::mesh::Selector( *(ss->second) ) &
      // and only if the part is local
      stk::mesh::Selector( metaData.locally_owned_part() );

    std::vector< stk::mesh::Entity * > sides ;
    stk::mesh::get_selected_entities( select_owned_in_sspart , // sides local to this processor
				      bulkData.buckets( metaData.side_rank() ) ,
				      sides ); // store the result in "sides"

    *out << "STKDisc: sideset "<< ss->first <<" has size " << sides.size() << "  on Proc 0." << std::endl;

    // loop over the sides to see what they are, then fill in the data holder
    // for side set options, look at $TRILINOS_DIR/packages/stk/stk_usecases/mesh/UseCase_13.cpp

    for (std::size_t localSideID=0; localSideID < sides.size(); localSideID++) {

      stk::mesh::Entity &sidee = *sides[localSideID];

      const stk::mesh::PairIterRelation side_elems = sidee.relations(element_rank); // get the elements
            // containing the side. Note that if the side is internal, it will show up twice in the
            // element list, once for each element that contains it.

      TEUCHOS_TEST_FOR_EXCEPTION(side_elems.size() != 1, std::logic_error,
			   "STKDisc: cannot figure out side set topology for side set " << ss->first << std::endl);

      const stk::mesh::Entity & elem = *side_elems[0].entity();

      SideStruct sStruct;

      // Save elem id. This is the global element id
      sStruct.elem_GID = gid(elem);

      int workset = elemGIDws[sStruct.elem_GID].ws; // Get the ws that this element lives in

      // Save elem id. This is the local element id within the workset
      sStruct.elem_LID = elemGIDws[sStruct.elem_GID].LID;

      // Save the side identifier inside of the element. This starts at zero here.
      sStruct.side_local_id = determine_local_side_id(elem, sidee);

      // Save the index of the element block that this elem lives in
      sStruct.elem_ebIndex = stkMeshStruct->ebNameToIndex[wsEBNames[workset]];

      SideSetList& ssList = sideSets[workset];   // Get a ref to the side set map for this ws
      SideSetList::iterator it = ssList.find(ss->first); // Get an iterator to the correct sideset (if
                                                                // it exists)

      if(it != ssList.end()) // The sideset has already been created

        it->second.push_back(sStruct); // Save this side to the vector that belongs to the name ss->first

      else { // Add the key ss->first to the map, and the side vector to that map

        std::vector<SideStruct> tmpSSVec;
        tmpSSVec.push_back(sStruct);

        ssList.insert(SideSetList::value_type(ss->first, tmpSSVec));

      }

    }

    ss++;
  }
}