Ejemplo n.º 1
0
      typename viennagrid::result_of::point< viennagrid::element<CellTagT, WrappedConfigT> >::type
      outer_cell_normal_at_facet(viennagrid::element<CellTagT,             WrappedConfigT> const & cell,
                                 viennagrid::element<viennagrid::line_tag, WrappedConfigT> const & facet)
      {
        typedef viennagrid::element<viennagrid::line_tag, WrappedConfigT>            FacetType;
        typedef typename viennagrid::result_of::point<FacetType>::type               PointType;
        typedef typename viennagrid::result_of::const_vertex_range<FacetType>::type  VertexRange;

        VertexRange facet_vertices(facet);
        PointType facet_vec = viennagrid::point(facet_vertices[1]) - viennagrid::point(facet_vertices[0]);
        PointType facet_centroid_vec = viennagrid::centroid(cell) - viennagrid::point(facet_vertices[0]);

        PointType edge_normal(facet_vec[1], -facet_vec[0]); // create one normal to line

        if (viennagrid::inner_prod(facet_centroid_vec, edge_normal) > 0) // normal vector is pointing into cell, hence flip
          edge_normal *= -1;

        return edge_normal / viennagrid::norm(edge_normal);
      }
Ejemplo n.º 2
0
void updateBoVec<2, MEdge>(
  const int normalSource, const MVertex *const vertex, const int zoneIndex,
  const int vertIndex,
  const CCon::FaceVector<MZoneBoundary<2>::GlobalVertexData<MEdge>::FaceDataB>
    &faces,
  ZoneBoVec &zoneBoVec, BCPatchIndex &patch, bool &warnNormFromElem)
{
  GEntity *ent;
  if(normalSource == NormalSourceElement) goto getNormalFromElements;
  ent = vertex->onWhat();
  if(ent == 0) {
    goto getNormalFromElements;
    // No entity: try to find a normal from the faces
  }
  else {
    switch(ent->dim()) {
    case 0:

      /*--------------------------------------------------------------------*
       * In this case, there are possibly two GEdges from this zone
       * connected to the vertex.  If the angle between the two edges is
       * significant, the BC patch will be split and this vertex will be
       * written in both patches with different normals.  If the angle is
       * small, or only one GEdge belongs to this zone, then the vertex will
       * only be written to one patch.
       *--------------------------------------------------------------------*/

      {
        // Find edge entities that are connected to elements in the zone
        std::vector<std::pair<GEdge *, int> > useGEdge;
        const int nFace = faces.size();
        for(int iFace = 0; iFace != nFace; ++iFace) {
          if(zoneIndex == faces[iFace].zoneIndex) {
            MEdge mEdge =
              faces[iFace].parentElement->getEdge(faces[iFace].parentFace);
            // Get the other vertex on the mesh edge.
            MVertex *vertex2 = mEdge.getMinVertex();
            if(vertex2 == vertex) vertex2 = mEdge.getMaxVertex();
            // Check if the entity associated with vertex2 is a line and
            // is also connected to vertex.  If so, add it to the container of
            // edge entities that will be used to determine the normal
            GEntity *const ent2 = vertex2->onWhat();
            if(ent2->dim() == 1) {
              useGEdge.push_back(
                std::pair<GEdge *, int>(static_cast<GEdge *>(ent2), iFace));
            }
          }
        }

        //--'useGEdge' now contains the edge entities that will be used to
        // determine
        //--the normals

        switch(useGEdge.size()) {
        case 0:
          //           goto getNormalFromElements;
          // We probably don't want BC data if none of the faces attatched to
          // this vertex and in this zone are on the boundary.
          break;

        case 1: {
          const GEdge *const gEdge =
            static_cast<const GEdge *>(useGEdge[0].first);
          SVector3 boNormal;
          if(edge_normal(vertex, zoneIndex, gEdge, faces, boNormal))
            goto getNormalFromElements;
          zoneBoVec.push_back(VertexBoundary(zoneIndex, gEdge->tag(), boNormal,
                                             const_cast<MVertex *>(vertex),
                                             vertIndex));
          patch.add(gEdge->tag());
        } break;

        case 2: {
          // Get the first normal
          const GEdge *const gEdge1 =
            static_cast<const GEdge *>(useGEdge[0].first);
          SVector3 boNormal1;
          if(edge_normal(vertex, zoneIndex, gEdge1, faces, boNormal1,
                         useGEdge[0].second))
            goto getNormalFromElements;

          // Get the second normal
          const GEdge *const gEdge2 =
            static_cast<const GEdge *>(useGEdge[1].first);
          SVector3 boNormal2;
          if(edge_normal(vertex, zoneIndex, gEdge2, faces, boNormal2,
                         useGEdge[1].second))
            goto getNormalFromElements;

          if(dot(boNormal1, boNormal2) < 0.98) {
            //--Write 2 separate patches

            zoneBoVec.push_back(
              VertexBoundary(zoneIndex, gEdge1->tag(), boNormal1,
                             const_cast<MVertex *>(vertex), vertIndex));
            patch.add(gEdge1->tag());
            zoneBoVec.push_back(
              VertexBoundary(zoneIndex, gEdge2->tag(), boNormal2,
                             const_cast<MVertex *>(vertex), vertIndex));
            patch.add(gEdge2->tag());
          }
          else {
            //--Write one patch

            boNormal1 += boNormal2;
            boNormal1 *= 0.5;
            zoneBoVec.push_back(
              VertexBoundary(zoneIndex, gEdge1->tag(), boNormal1,
                             const_cast<MVertex *>(vertex), vertIndex));
            patch.addPair(gEdge1->tag(), gEdge2->tag());
          }
        } break;

        default:
          Msg::Error("Internal error based on 2-D boundary assumptions (file "
                     "\'MZoneBoundary.cpp').  Boundary vertices may be "
                     "incorrect");
          break;
        }
      }
      break;
    case 1:

      /*--------------------------------------------------------------------*
       * The vertex exists on an edge and belongs to only 1 BC patch.
       *--------------------------------------------------------------------*/

      {
        SVector3 boNormal;
        if(edge_normal(vertex, zoneIndex, static_cast<const GEdge *>(ent),
                       faces, boNormal))
          goto getNormalFromElements;
        zoneBoVec.push_back(VertexBoundary(zoneIndex, ent->tag(), boNormal,
                                           const_cast<MVertex *>(vertex),
                                           vertIndex));
        patch.add(ent->tag());
      }
      break;

    default: goto getNormalFromElements;
    }
  }
  return;

getNormalFromElements:;

  /*--------------------------------------------------------------------*
   * Geometry information cannot be used - generate normals from the
   * elements
   *--------------------------------------------------------------------*/

  {
    if(warnNormFromElem && normalSource == 1) {
      Msg::Warning("Some or all boundary normals were determined from mesh "
                   "elements instead of from the geometry");
      warnNormFromElem = false;
    }
    // The mesh plane normal is computed from all elements attached to the
    // vertex
    SVector3 meshPlaneNormal(0.); // This normal is perpendicular to the
                                  // plane of the mesh
    const int nFace = faces.size();
    for(int iFace = 0; iFace != nFace; ++iFace) {
      if(faces[iFace].zoneIndex == zoneIndex) {
        // Make sure all the planes go in the same direction
        //**Required?
        SVector3 mpnt = faces[iFace].parentElement->getFace(0).normal();
        if(dot(mpnt, meshPlaneNormal) < 0.) mpnt.negate();
        meshPlaneNormal += mpnt;
      }
    }
    // Sum the normals from each element.  The tangent is computed from all
    // faces in the zone attached to the vertex and is weighted by the length of
    // the edge.  Each tangent has to be converted independently into an
    // inwards-pointing normal.
    SVector3 boNormal(0.);
    for(int iFace = 0; iFace != nFace; ++iFace) {
      if(faces[iFace].zoneIndex == zoneIndex) {
        const SVector3 tangent =
          faces[iFace]
            .parentElement->getEdge(faces[iFace].parentFace)
            .tangent();
        // Normal to the boundary (unknown direction)
        SVector3 bnt = crossprod(tangent, meshPlaneNormal);
        // Inwards normal
        const SVector3 inwards(vertex->point(),
                               faces[iFace].parentElement->barycenter());
        if(dot(bnt, inwards) < 0.) bnt.negate();
        boNormal += bnt;
      }
    }
    boNormal.normalize();
    zoneBoVec.push_back(VertexBoundary(
      zoneIndex, 0, boNormal, const_cast<MVertex *>(vertex), vertIndex));
    patch.add(0);
  }
}