bool Mesh::bndDistAndGradients(int iEl, double &f , std::vector<double> &gradF, double eps) { MElement *element = _el[iEl]; f = 0.; // dommage ;-) if (element->getDim() != 2) return false; int currentId = 0; std::vector<int> vertex2param(element->getNumVertices()); for (size_t i = 0; i < element->getNumVertices(); ++i) { if (_el2FV[iEl][i] >= 0) { vertex2param[i] = currentId; currentId += _nPCFV[_el2FV[iEl][i]]; } else vertex2param[i] = -1; } gradF.clear(); gradF.resize(currentId, 0.); const nodalBasis &elbasis = *element->getFunctionSpace(); bool edgeFound = false; for (int iEdge = 0; iEdge < element->getNumEdges(); ++iEdge) { int clId = elbasis.getClosureId(iEdge, 1); const std::vector<int> &closure = elbasis.closures[clId]; std::vector<MVertex *> vertices; GEdge *edge = NULL; for (size_t i = 0; i < closure.size(); ++i) { MVertex *v = element->getVertex(closure[i]); vertices.push_back(v); // only valid in 2D if ((int)i >= 2 && v->onWhat() && v->onWhat()->dim() == 1) { edge = v->onWhat()->cast2Edge(); } } if (edge) { edgeFound = true; std::vector<double> localgrad; std::vector<SPoint3> nodes(closure.size()); std::vector<double> params(closure.size()); std::vector<bool> onedge(closure.size()); for (size_t i = 0; i < closure.size(); ++i) { nodes[i] = _xyz[_el2V[iEl][closure[i]]]; onedge[i] = element->getVertex(closure[i])->onWhat() == edge && _el2FV[iEl][closure[i]] >= 0; if (onedge[i]) { params[i] = _uvw[_el2FV[iEl][closure[i]]].x(); }else reparamMeshVertexOnEdge(element->getVertex(closure[i]), edge, params[i]); } f += computeBndDistAndGradient(edge, params, vertices, *BasisFactory::getNodalBasis(elbasis.getClosureType(clId)), nodes, onedge, localgrad, eps); for (size_t i = 0; i < closure.size(); ++i) { if (onedge[i]) gradF[vertex2param[closure[i]]] += localgrad[i]; } } } return edgeFound; }
int edge_normal (const MVertex *const vertex, const int zoneIndex, const GEdge *const gEdge, const CCon::FaceVector<MZoneBoundary<2>::GlobalVertexData<MEdge>::FaceDataB> &faces, SVector3 &boNormal, const int onlyFace = -1) { double par=0.0; // Note: const_cast used to match MVertex.cpp interface if(!reparamMeshVertexOnEdge(const_cast<MVertex*>(vertex), gEdge, par)) return 1; const SVector3 tangent(gEdge->firstDer(par)); // Tangent to the boundary face SPoint3 interior(0., 0., 0.); // An interior point SVector3 meshPlaneNormal(0.); // This normal is perpendicular to the // plane of the mesh // The interior point and mesh plane normal are computed from all elements in // the zone. int cFace = 0; int iFace = 0; int nFace = faces.size(); if ( onlyFace >= 0 ) { iFace = onlyFace; nFace = onlyFace + 1; } for(; iFace != nFace; ++iFace) { if(faces[iFace].zoneIndex == zoneIndex) { ++cFace; interior += faces[iFace].parentElement->barycenter(); // 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; } } interior /= cFace; // Normal to the boundary edge (but unknown direction) boNormal = crossprod(tangent, meshPlaneNormal); boNormal.normalize(); // Direction vector from vertex to interior (inwards). The normal should // point in the same direction. if(dot(boNormal, SVector3(vertex->point(), interior)) < 0.) boNormal.negate(); return 0; }
double taylorDistanceEdge(MLine *l, GEdge *ge) { const int nV = l->getNumVertices(); const GradientBasis *gb = BasisFactory::getGradientBasis(FuncSpaceData(l)); // Coordinates of vertices fullMatrix<double> nodesXYZ(nV, 3); l->getNodesCoord(nodesXYZ); // Tangent to CAD at vertices std::vector<SVector3> tanCAD(nV); for (int i=0; i<nV; i++) { double tCAD; reparamMeshVertexOnEdge(l->getVertex(i), ge, tCAD); tanCAD[i] = ge->firstDer(tCAD); tanCAD[i].normalize(); } // Compute distance return sqrt(taylorDistanceSq1D(gb, nodesXYZ, tanCAD)); }