void Mesh::calcScaledNormalEl2D(const std::map<MElement*,GEntity*> &element2entity, int iEl) { const JacobianBasis *jac = _el[iEl]->getJacobianFuncSpace(); fullMatrix<double> primNodesXYZ(jac->getNumPrimMapNodes(),3); SVector3 geoNorm(0.,0.,0.); std::map<MElement*,GEntity*>::const_iterator itEl2ent = element2entity.find(_el[iEl]); GEntity *ge = (itEl2ent == element2entity.end()) ? 0 : itEl2ent->second; const bool hasGeoNorm = ge && (ge->dim() == 2) && ge->haveParametrization(); for (int i=0; i<jac->getNumPrimMapNodes(); i++) { const int &iV = _el2V[iEl][i]; primNodesXYZ(i,0) = _xyz[iV].x(); primNodesXYZ(i,1) = _xyz[iV].y(); primNodesXYZ(i,2) = _xyz[iV].z(); if (hasGeoNorm && (_vert[iV]->onWhat() == ge)) { double u, v; _vert[iV]->getParameter(0,u); _vert[iV]->getParameter(1,v); geoNorm += ((GFace*)ge)->normal(SPoint2(u,v)); } } if (hasGeoNorm && (geoNorm.normSq() == 0.)) { SPoint2 param = ((GFace*)ge)->parFromPoint(_el[iEl]->barycenter(true),false); geoNorm = ((GFace*)ge)->normal(param); } fullMatrix<double> &elNorm = _scaledNormEl[iEl]; elNorm.resize(1,3); const double norm = jac->getPrimNormal2D(primNodesXYZ,elNorm); double factor = 1./norm; if (hasGeoNorm) { const double scal = geoNorm(0)*elNorm(0,0)+geoNorm(1)*elNorm(0,1)+geoNorm(2)*elNorm(0,2); if (scal < 0.) factor = -factor; } elNorm.scale(factor); // Re-scaling normal here is faster than an extra scaling operation on the Jacobian }
Mesh::Mesh(const std::map<MElement*,GEntity*> &element2entity, const std::set<MElement*> &els, std::set<MVertex*> &toFix, bool fixBndNodes, bool fastJacEval) : _fastJacEval(fastJacEval) { _dim = (*els.begin())->getDim(); // Initialize elements, vertices, free vertices and element->vertices // connectivity const int nElements = els.size(); _nPC = 0; _el.resize(nElements); _el2FV.resize(nElements); _el2V.resize(nElements); _nBezEl.resize(nElements); _nNodEl.resize(nElements); _indPCEl.resize(nElements); int iEl = 0; bool nonGeoMove = false; for(std::set<MElement*>::const_iterator it = els.begin(); it != els.end(); ++it, ++iEl) { _el[iEl] = *it; const JacobianBasis *jac = _el[iEl]->getJacobianFuncSpace(); _nBezEl[iEl] = _fastJacEval ? jac->getNumJacNodesFast() : jac->getNumJacNodes(); _nNodEl[iEl] = jac->getNumMapNodes(); for (int iVEl = 0; iVEl < jac->getNumMapNodes(); iVEl++) { MVertex *vert = _el[iEl]->getVertex(iVEl); GEntity *ge = vert->onWhat(); const int vDim = ge->dim(); const bool hasParam = ge->haveParametrization(); int iV = addVert(vert); _el2V[iEl].push_back(iV); if ((vDim > 0) && (toFix.find(vert) == toFix.end()) && (!fixBndNodes || vDim == _dim)) { // Free vertex? ParamCoord *param; if (vDim == 3) param = new ParamCoordPhys3D(); else if (hasParam) param = new ParamCoordParent(vert); else { if (vDim == 2) param = new ParamCoordLocalSurf(vert); else param = new ParamCoordLocalLine(vert); nonGeoMove = true; } int iFV = addFreeVert(vert,iV,vDim,param,toFix); _el2FV[iEl].push_back(iFV); for (int i=_startPCFV[iFV]; i<_startPCFV[iFV]+vDim; i++) _indPCEl[iEl].push_back(i); } else _el2FV[iEl].push_back(-1); } } if (nonGeoMove) Msg::Info("WARNING: Some vertices will be moved along local lines " "or planes, they may not remain on the exact geometry"); // Initial coordinates _ixyz.resize(nVert()); for (int iV = 0; iV < nVert(); iV++) _ixyz[iV] = _vert[iV]->point(); _iuvw.resize(nFV()); for (int iFV = 0; iFV < nFV(); iFV++) _iuvw[iFV] = _paramFV[iFV]->getUvw(_freeVert[iFV]); // Set current coordinates _xyz = _ixyz; _uvw = _iuvw; // Set normals to 2D elements (with magnitude of inverse Jacobian) or initial // Jacobians of 3D elements if (_dim == 2) { _scaledNormEl.resize(nEl()); for (int iEl = 0; iEl < nEl(); iEl++) calcScaledNormalEl2D(element2entity,iEl); } else { _invStraightJac.resize(nEl(),1.); double dumJac[3][3]; for (int iEl = 0; iEl < nEl(); iEl++) _invStraightJac[iEl] = 1. / fabs(_el[iEl]->getPrimaryJacobian(0.,0.,0.,dumJac)); } }