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; }
void backgroundMesh2D::updateSizes() { DoubleStorageType::iterator itv = sizeField.begin(); for ( ; itv != sizeField.end(); ++itv) { SPoint2 p; MVertex *v = _2Dto3D[itv->first]; double lc; if (v->onWhat()->dim() == 0) { lc = sizeFactor * BGM_MeshSize(v->onWhat(), 0,0,v->x(),v->y(),v->z()); } else if (v->onWhat()->dim() == 1) { double u; v->getParameter(0, u); lc = sizeFactor * BGM_MeshSize(v->onWhat(), u, 0, v->x(), v->y(), v->z()); } else { GFace *face = dynamic_cast<GFace*>(gf); if(!face) { Msg::Error("Entity is not a face in background mesh"); return; } reparamMeshVertexOnFace(v, face, p); lc = sizeFactor * BGM_MeshSize(face, p.x(), p.y(), v->x(), v->y(), v->z()); } // printf("2D -- %g %g 3D -- %g %g\n",p.x(),p.y(),v->x(),v->y()); itv->second = min(lc,itv->second); itv->second = max(itv->second, sizeFactor * CTX::instance()->mesh.lcMin); itv->second = min(itv->second, sizeFactor * CTX::instance()->mesh.lcMax); } // do not allow large variations in the size field // (Int. J. Numer. Meth. Engng. 43, 1143-1165 (1998) MESH GRADATION // CONTROL, BOROUCHAKI, HECHT, FREY) std::set<MEdge,Less_Edge> edges; for (unsigned int i = 0; i < getNumMeshElements(); i++) { for (int j = 0; j < getElement(i)->getNumEdges(); j++) { edges.insert(getElement(i)->getEdge(j)); } } const double _beta = 1.3; for (int i=0; i<0; i++) { std::set<MEdge,Less_Edge>::iterator it = edges.begin(); for ( ; it != edges.end(); ++it) { MVertex *v0 = it->getVertex(0); MVertex *v1 = it->getVertex(1); MVertex *V0 = _2Dto3D[v0]; MVertex *V1 = _2Dto3D[v1]; DoubleStorageType::iterator s0 = sizeField.find(V0); DoubleStorageType::iterator s1 = sizeField.find(V1); if (s0->second < s1->second)s1->second = min(s1->second,_beta*s0->second); else s0->second = min(s0->second,_beta*s1->second); } } }
static double _relocateVertex(GFace *gf, MVertex *ver, const std::vector<MElement *> <, double tol) { if(ver->onWhat()->dim() != 2) return 2.0; SPoint2 p1(0, 0); SPoint2 p2; if(ver->getParameter(0, p2[0])) { ver->getParameter(1, p2[1]); } else { return _relocateVertex2(gf, ver, lt, tol); } std::size_t counter = 0; for(std::size_t i = 0; i < lt.size(); i++) { for(std::size_t j = 0; j < lt[i]->getNumVertices(); j++) { MVertex *v = lt[i]->getVertex(j); SPoint2 pp; reparamMeshVertexOnFace(v, gf, pp); counter++; if(v->onWhat()->dim() == 1) { GEdge *ge = dynamic_cast<GEdge *>(v->onWhat()); // do not take any chance if(ge->isSeam(gf)) return 2.0; } p1 += pp; } } p1 *= 1. / (double)counter; double worst; double xi = Maximize_Quality_Golden_Section(ver, gf, p1, p2, lt, tol, worst); // if (xi != 0) printf("xi = %g\n",xi); SPoint2 p = p1 * (1 - xi) + p2 * xi; GPoint pp = gf->point(p); if(!pp.succeeded()) return 2.0; ver->x() = pp.x(); ver->y() = pp.y(); ver->z() = pp.z(); ver->setParameter(0, pp.u()); ver->setParameter(1, pp.v()); return worst; }
bool GEdge::computeDistanceFromMeshToGeometry (double &d2, double &dmax) { d2 = 0.0; dmax = 0.0; if (geomType() == Line) return true; if (!lines.size())return false; IntPt *pts; int npts; lines[0]->getIntegrationPoints(2*lines[0]->getPolynomialOrder(), &npts, &pts); for (unsigned int i = 0; i < lines.size(); i++){ MLine *l = lines[i]; double t[256]; for (int j=0; j< l->getNumVertices();j++){ MVertex *v = l->getVertex(j); if (v->onWhat() == getBeginVertex()){ t[j] = getLowerBound(); } else if (v->onWhat() == getEndVertex()){ t[j] = getUpperBound(); } else { v->getParameter(0,t[j]); } } for (int j=0;j<npts;j++){ SPoint3 p; l->pnt(pts[j].pt[0],0,0,p); double tinit = l->interpolate(t,pts[j].pt[0],0,0); GPoint pc = closestPoint(p, tinit); if (!pc.succeeded())continue; double dsq = (pc.x()-p.x())*(pc.x()-p.x()) + (pc.y()-p.y())*(pc.y()-p.y()) + (pc.z()-p.z())*(pc.z()-p.z()); d2 += pts[i].weight * fabs(l->getJacobianDeterminant(pts[j].pt[0],0,0)) * dsq; dmax = std::max(dmax,sqrt(dsq)); } } d2 = sqrt(d2); return true; }
std::set<MVertex *> BGMBase::get_vertices_of_maximum_dim(int dim) { std::set<MVertex *> bnd_vertices; for(unsigned int i = 0; i < gf->getNumMeshElements(); i++) { MElement *element = gf->getMeshElement(i); for(std::size_t j = 0; j < element->getNumVertices(); j++) { MVertex *vertex = element->getVertex(j); if(vertex->onWhat()->dim() <= dim) bnd_vertices.insert(vertex); } } return bnd_vertices; }
void Mesh::getGEntityPositions(std::vector<SPoint3> &xyz, std::vector<SPoint3> &uvw) { xyz.resize(nVert()); uvw.resize(nFV()); for (int iV = 0; iV < nVert(); iV++) xyz[iV] = SPoint3(_vert[iV]->x(),_vert[iV]->y(),_vert[iV]->z()); for (int iFV = 0; iFV < nFV(); iFV++){ MVertex *v = _freeVert[iFV]; if (v->onWhat()->dim() == 1){ double t; v->getParameter(0,t); uvw[iFV] = SPoint3(t,0,0); } if (v->onWhat()->dim() == 2){ double uu,vv; v->getParameter(0,uu); v->getParameter(1,vv); uvw[iFV] = SPoint3(uu,vv,0); } } }
static void drawVerticesPerElement(drawContext *ctx, GEntity *e, std::vector<T*> &elements) { for(unsigned int i = 0; i < elements.size(); i++){ MElement *ele = elements[i]; for(int j = 0; j < ele->getNumVertices(); j++){ MVertex *v = ele->getVertex(j); // FIXME isElementVisible() can be slow: we should also use a // vertex array for drawing vertices... if(isElementVisible(ele) && v->getVisibility()){ if(CTX::instance()->mesh.points) { if(CTX::instance()->mesh.colorCarousel == 0 || CTX::instance()->mesh.volumesFaces || CTX::instance()->mesh.surfacesFaces){ // by element type if(v->getPolynomialOrder() > 1) glColor4ubv((GLubyte *) & CTX::instance()->color.mesh.vertexSup); else glColor4ubv((GLubyte *) & CTX::instance()->color.mesh.vertex); } else{ unsigned int col = getColorByEntity(e); glColor4ubv((GLubyte *) & col); } if(CTX::instance()->mesh.pointType) ctx->drawSphere(CTX::instance()->mesh.pointSize, v->x(), v->y(), v->z(), CTX::instance()->mesh.light); else{ glBegin(GL_POINTS); glVertex3d(v->x(), v->y(), v->z()); glEnd(); } } if(CTX::instance()->mesh.pointsNum) drawVertexLabel(ctx, v->onWhat() ? v->onWhat() : e, v); } } } }
bool OptHOM::addBndObjGrad(double factor, double &Obj, alglib::real_1d_array &gradObj) { // set the mesh to its present position std::vector<SPoint3> xyz,uvw; mesh.getGEntityPositions(xyz,uvw); mesh.updateGEntityPositions(); //could be better (e.g. store the model in the Mesh:: datastrucure) GModel *gm = GModel::current(); // for all model edges, compute the error between the geometry and the mesh maxDistCAD = 0.0; double distCAD = 0.0; for (GModel::eiter it = gm->firstEdge(); it != gm->lastEdge(); ++it){ // do not do straight lines if ((*it)->geomType() == GEntity::Line)continue; // look at all mesh lines std::vector<bool> doWeCompute((*it)->lines.size()); for (unsigned int i=0;i<(*it)->lines.size(); i++){ doWeCompute[i] = false; for (unsigned int j=0;j<(*it)->lines[i]->getNumVertices(); j++){ int index = mesh.getFreeVertexStartIndex((*it)->lines[i]->getVertex(j)); if (index >=0){ doWeCompute[i] = true; continue; } } } std::vector<double> dist((*it)->lines.size()); for (unsigned int i=0;i<(*it)->lines.size(); i++){ if (doWeCompute[i]){ // compute the distance from the geometry to the mesh dist[i] = MLineGEdgeDistance ( (*it)->lines[i] , *it ); maxDistCAD = std::max(maxDistCAD,dist[i]); distCAD += dist [i] * factor; } } // be clever to compute the derivative : iterate on all // Distance = \sum_{lines} Distance (line, GEdge) // For a high order vertex, we compute the derivative only by // recomputing the distance to one only line const double eps = 1.e-6; for (unsigned int i=0;i<(*it)->lines.size(); i++){ if (doWeCompute[i]){ for (int j=2 ; j<(*it)->lines[i]->getNumVertices() ; j++){ MVertex *v = (*it)->lines[i]->getVertex(j); int index = mesh.getFreeVertexStartIndex(v); // printf("%d %d (%d %d)\n",v->getNum(),index,v->onWhat()->tag(),v->onWhat()->dim()); if (index >= 0){ double t; v->getParameter(0,t); SPoint3 pp (v->x(),v->y(),v->z()); GPoint gp = (*it)->point(t+eps); v->setParameter(0,t+eps); v->setXYZ(gp.x(),gp.y(),gp.z()); double dist2 = MLineGEdgeDistance ( (*it)->lines[i] , *it ); double deriv = (dist2 - dist[i])/eps; v->setXYZ(pp.x(),pp.y(),pp.z()); v->setParameter(0,t); // printf("%g %g %g\n",dist[i],dist2, MLineGEdgeDistance ( (*it)->lines[i] , *it )); // get the index of the vertex gradObj[index] += deriv * factor; } } } // printf("done\n"); // For a low order vertex classified on the GEdge, we recompute // two distances for the two MLines connected to the vertex for (unsigned int i=0;i<(*it)->lines.size()-1; i++){ MVertex *v = (*it)->lines[i]->getVertex(1); int index = mesh.getFreeVertexStartIndex(v); if (index >= 0){ double t; v->getParameter(0,t); SPoint3 pp (v->x(),v->y(),v->z()); GPoint gp = (*it)->point(t+eps); v->setParameter(0,t+eps); v->setXYZ(gp.x(),gp.y(),gp.z()); MLine *l1 = (*it)->lines[i]; MLine *l2 = (*it)->lines[i+1]; // printf("%d %d -- %d %d\n",l1->getVertex(0)->getNum(),l1->getVertex(1)->getNum(),l2->getVertex(0)->getNum(),l2->getVertex(1)->getNum()); double deriv = (MLineGEdgeDistance ( l1 , *it ) - dist[i]) /eps + (MLineGEdgeDistance ( l2 , *it ) - dist[i+1])/eps; v->setXYZ(pp.x(),pp.y(),pp.z()); v->setParameter(0,t); gradObj[index] += deriv * factor; } } } } // printf("computing distance : 1D part %12.5E\n",distCAD); // now the 3D part ! std::vector<std::vector<SVector3> > gsfT; computeGradSFAtNodes ( (*gm->firstFace())->triangles[0],gsfT); std::map<MVertex*,SVector3> normalsToCAD; for(GModel::fiter it = gm->firstFace(); it != gm->lastFace(); ++it){ // do not do plane surfaces if ((*it)->geomType() == GEntity::Plane)continue; std::map<MTriangle*,double> dist; std::vector<bool> doWeCompute((*it)->triangles.size()); for (unsigned int i=0;i<(*it)->triangles.size(); i++){ doWeCompute[i] = false; for (unsigned int j=0;j<(*it)->triangles[i]->getNumVertices(); j++){ int index = mesh.getFreeVertexStartIndex((*it)->triangles[i]->getVertex(j)); if (index >=0){ doWeCompute[i] = true; } } if (doWeCompute[i]){ for (unsigned int j=0;j<(*it)->triangles[i]->getNumVertices(); j++){ MVertex *v = (*it)->triangles[i]->getVertex(j); if (normalsToCAD.find(v) == normalsToCAD.end()){ SPoint2 p_cad; reparamMeshVertexOnFace(v, *it, p_cad); SVector3 tg_cad = (*it)->normal(p_cad); tg_cad.normalize(); normalsToCAD[v] = tg_cad; } } } } for (unsigned int i=0;i<(*it)->triangles.size(); i++){ // compute the distance from the geometry to the mesh if(doWeCompute[i]){ const double d = MFaceGFaceDistanceOld((*it)->triangles[i], *it, &gsfT, &normalsToCAD); dist[(*it)->triangles[i]] = d; maxDistCAD = std::max(maxDistCAD,d); distCAD += d * factor; } } // be clever again to compute the derivatives const double eps = 1.e-6; for (unsigned int i=0;i<(*it)->triangles.size(); i++){ if(doWeCompute[i]){ for (unsigned int j=0;j<(*it)->triangles[i]->getNumVertices(); j++){ // for (; itm !=v2t.end(); ++itm){ MVertex *v = (*it)->triangles[i]->getVertex(j); if(v->onWhat()->dim() == 1){ int index = mesh.getFreeVertexStartIndex(v); if (index >= 0){ MTriangle *t = (*it)->triangles[i]; GEdge *ge = v->onWhat()->cast2Edge(); double t_; v->getParameter(0,t_); SPoint3 pp (v->x(),v->y(),v->z()); GPoint gp = ge->point(t_+eps); v->setParameter(0,t_+eps); v->setXYZ(gp.x(),gp.y(),gp.z()); const double distT = dist[t]; double deriv = (MFaceGFaceDistanceOld(t, *it, &gsfT, &normalsToCAD) - distT) /eps; v->setXYZ(pp.x(),pp.y(),pp.z()); v->setParameter(0,t_); gradObj[index] += deriv * factor; } } if(v->onWhat() == *it){ int index = mesh.getFreeVertexStartIndex(v); if (index >= 0){ MTriangle *t = (*it)->triangles[i]; double uu,vv; v->getParameter(0,uu); v->getParameter(1,vv); SPoint3 pp (v->x(),v->y(),v->z()); const double distT = dist[t]; GPoint gp = (*it)->point(uu+eps,vv); v->setParameter(0,uu+eps); v->setXYZ(gp.x(),gp.y(),gp.z()); double deriv = (MFaceGFaceDistanceOld(t, *it, &gsfT, &normalsToCAD) - distT) /eps; v->setXYZ(pp.x(),pp.y(),pp.z()); v->setParameter(0,uu); gradObj[index] += deriv * factor; gp = (*it)->point(uu,vv+eps); v->setParameter(1,vv+eps); v->setXYZ(gp.x(),gp.y(),gp.z()); deriv = (MFaceGFaceDistanceOld(t, *it, &gsfT, &normalsToCAD) - distT) /eps; v->setXYZ(pp.x(),pp.y(),pp.z()); v->setParameter(1,vv); gradObj[index+1] += deriv * factor; } } } } } } mesh.updateGEntityPositions(xyz,uvw); Obj +=distCAD; // printf("computing distance : 2D part %12.5E\n",distCAD); // printf("%22.15E\n",distCAD); return true; }
PView *GMSH_BubblesPlugin::execute(PView *v) { double shrink = (double)BubblesOptions_Number[0].def; std::string fileName = BubblesOptions_String[0].def; FILE *fp = Fopen(fileName.c_str(), "w"); if(!fp){ Msg::Error("Could not open output file '%s'", fileName.c_str()); return v; } GModel *m = GModel::current(); int p = m->getMaxElementaryNumber(0) + 1; int l = m->getMaxElementaryNumber(1) + 1; int s = m->getMaxElementaryNumber(2) + 1; int ll = s, ps = 1; SBoundingBox3d bbox = m->bounds(); double lc = norm(SVector3(bbox.max(), bbox.min())) / 100; fprintf(fp, "lc = %g;\n", lc); for(GModel::viter vit = m->firstVertex(); vit != m->lastVertex(); vit++) (*vit)->writeGEO(fp, "lc"); for(GModel::eiter eit = m->firstEdge(); eit != m->lastEdge(); eit++) (*eit)->writeGEO(fp); for(GModel::fiter fit = m->firstFace(); fit != m->lastFace(); fit++){ (*fit)->writeGEO(fp); fprintf(fp, "Delete { Surface {%d}; }\n", (*fit)->tag()); int sbeg = s; int llbeg = ll; // compute vertex-to-triangle_barycenter map std::map<MVertex*, std::vector<SPoint3> > v2t; for(unsigned int i = 0; i < (*fit)->triangles.size(); i++) for(int j = 0; j < 3; j++) v2t[(*fit)->triangles[i]->getVertex(j)].push_back((*fit)->triangles[i]->barycenter()); // add boundary vertices in map to get cells "closer" to the boundary for(std::map<MVertex*, std::vector<SPoint3> >::iterator it = v2t.begin(); it != v2t.end(); it++){ MVertex *v = it->first; if(v->onWhat() && v->onWhat()->dim() < 2) it->second.push_back(SPoint3(it->first->x(), it->first->y(), it->first->z())); } for(std::map<MVertex*, std::vector<SPoint3> >::iterator it = v2t.begin(); it != v2t.end(); it++){ if(it->second.size() > 2){ // get barycenter of cell boundary points and order them SPoint3 bc; for(unsigned int i = 0; i < it->second.size(); i++) bc += it->second[i]; bc *= 1. / (double)it->second.size(); compareAngle comp(bc); std::sort(it->second.begin(), it->second.end(), comp); // shrink cells if(shrink){ for(unsigned int i = 0; i < it->second.size(); i++){ double dir[3] = {it->second[i].x() - bc.x(), it->second[i].y() - bc.y(), it->second[i].z() - bc.z()}; it->second[i][0] -= shrink * dir[0]; it->second[i][1] -= shrink * dir[1]; it->second[i][2] -= shrink * dir[2]; } } // create b-spline bounded surface for each cell int nump = it->second.size(); for(int i = 0; i < nump; i++){ SPoint3 &b(it->second[i]); fprintf(fp, "Point(%d) = {%.16g, %.16g, %.16g, lc};\n", p++, b.x(), b.y(), b.z()); } fprintf(fp, "BSpline(%d) = {", l++); for(int i = nump - 1; i >= 0; i--) fprintf(fp, "%d,", p - i - 1); fprintf(fp, "%d};\n", p - nump); fprintf(fp, "Line Loop(%d) = {%d};\n", ll++, l - 1); fprintf(fp, "Plane Surface(%d) = {%d};\n", s++, ll - 1); } } fprintf(fp, "Physical Surface(%d) = {%d:%d};\n", ps++, sbeg, s - 1); fprintf(fp, "Plane Surface(%d) = {%d, %d:%d};\n", s++, (*fit)->tag(), llbeg, ll - 1); fprintf(fp, "Physical Surface(%d) = {%d};\n", ps++, s - 1); } fclose(fp); return v; }
// apply a displacement that does not create elements that are // distorted over a value "thres" double highOrderTools::apply_incremental_displacement(double max_incr, std::vector<MElement*> & v, bool mixed, double thres, char *meshName, std::vector<MElement*> & disto) { #ifdef HAVE_PETSC // assume that the mesh is OK, yet already curved //linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>; linearSystemPETSc<double> *lsys = new linearSystemPETSc<double>; lsys->setParameter("petscOptions","-pc_type ilu"); lsys->setParameter("petscOptions","-ksp_monitor"); dofManager<double> myAssembler(lsys); elasticityMixedTerm El_mixed (0, 1.0, .333, _tag); elasticityTerm El (0, 1.0, .333, _tag); std::set<MVertex*> _vertices; //+++++++++ Boundary Conditions & Numbering +++++++++++++++++++++++++++++++ // fix all dof that correspond to vertices on the boundary // the value is equal for (unsigned int i = 0; i < v.size(); i++){ for (int j = 0; j < v[i]->getNumVertices(); j++){ MVertex *vert = v[i]->getVertex(j); _vertices.insert(vert); } } //+++++++++ Fix d tr(eps) = 0 +++++++++++++++++++++++++++++++ if (mixed){ for (unsigned int i = 0; i < disto.size(); i++){ for (int j = 0; j < disto[i]->getNumVertices(); j++){ MVertex *vert = disto[i]->getVertex(j); myAssembler.fixVertex(vert, 4, _tag, 0.0); } } } for (std::set<MVertex*>::iterator it = _vertices.begin(); it != _vertices.end(); ++it){ MVertex *vert = *it; std::map<MVertex*,SVector3>::iterator itt = _targetLocation.find(vert); // impose displacement @ boundary if (itt != _targetLocation.end() && vert->onWhat()->dim() < _dim){ myAssembler.fixVertex(vert, 0, _tag, itt->second.x()-vert->x()); myAssembler.fixVertex(vert, 1, _tag, itt->second.y()-vert->y()); myAssembler.fixVertex(vert, 2, _tag, itt->second.z()-vert->z()); } // ensure we do not touch any vertex that is on the boundary else if (vert->onWhat()->dim() < _dim){ myAssembler.fixVertex(vert, 0, _tag, 0); myAssembler.fixVertex(vert, 1, _tag, 0); myAssembler.fixVertex(vert, 2, _tag, 0); } // } if (_dim == 2)myAssembler.fixVertex(vert, 2, _tag, 0); // number vertices myAssembler.numberVertex(vert, 0, _tag); myAssembler.numberVertex(vert, 1, _tag); myAssembler.numberVertex(vert, 2, _tag); if (mixed){ myAssembler.numberVertex(vert, 3, _tag); myAssembler.numberVertex(vert, 4, _tag); } } if (myAssembler.sizeOfR()){ // assembly of the elasticity term on the for (unsigned int i = 0; i < v.size(); i++){ SElement se(v[i]); if (mixed) El_mixed.addToMatrix(myAssembler, &se); else El.addToMatrix(myAssembler, &se); } // solve the system lsys->systemSolve(); } // Move vertices @ maximum FILE *fd = Fopen ("d.msh","w"); fprintf(fd,"$MeshFormat\n2 0 8\n$EndMeshFormat\n$NodeData\n1\n" "\"tr(sigma)\"\n1\n0.0\n3\n1\n3\n%d\n", (int) _vertices.size()); for (std::set<MVertex*>::iterator it = _vertices.begin(); it != _vertices.end(); ++it){ double ax, ay, az; myAssembler.getDofValue(*it, 0, _tag, ax); myAssembler.getDofValue(*it, 1, _tag, ay); myAssembler.getDofValue(*it, 2, _tag, az); (*it)->x() += max_incr*ax; (*it)->y() += max_incr*ay; (*it)->z() += max_incr*az; fprintf(fd,"%d %g %g %g\n",(*it)->getIndex(), ax,ay,az); } fprintf(fd,"$EndNodeData\n"); fclose(fd); // Check now if elements are ok (*_vertices.begin())->onWhat()->model()->writeMSH(meshName); double percentage = max_incr * 100.; while(1){ std::vector<MElement*> disto; double minD; getDistordedElements(v, 0.5, disto, minD); if (minD < thres){ percentage -= 10.; for (std::set<MVertex*>::iterator it = _vertices.begin(); it != _vertices.end(); ++it){ double ax, ay, az; myAssembler.getDofValue(*it, 0, _tag, ax); myAssembler.getDofValue(*it, 1, _tag, ay); myAssembler.getDofValue(*it, 2, _tag, az); (*it)->x() -= .1*ax; (*it)->y() -= .1*ay; (*it)->z() -= .1*az; } } else break; } delete lsys; return percentage; #endif return 0.0; }
void highOrderTools::applySmoothingTo(std::vector<MElement*> &all, GFace *gf) { #ifdef HAVE_TAUCS linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>; #else linearSystemPETSc<double> *lsys = new linearSystemPETSc<double>; #endif // compute the straight sided positions of high order nodes that are // on the edges of the face in the UV plane dofManager<double> myAssembler(lsys); elasticityTerm El(0, 1.0, CTX::instance()->mesh.hoPoissonRatio, _tag); std::vector<MElement*> layer, v; double minD; getDistordedElements(all, CTX::instance()->mesh.hoThresholdMin, v, minD); int numBad = v.size(); const int nbLayers = CTX::instance()->mesh.hoNLayers; for (int i = 0; i < nbLayers; i++){ addOneLayer(all, v, layer); v.insert(v.end(), layer.begin(), layer.end()); } if (!v.size()) return; Msg::Info("Smoothing high order mesh : model face %d (%d elements considered in " "the elastic analogy, worst mapping %12.5E, %3d bad elements)", gf->tag(), v.size(),minD,numBad); addOneLayer(all, v, layer); std::set<MVertex*>::iterator it; std::set<MVertex*> verticesToMove; // on the last layer, fix displacement to 0 for (unsigned int i = 0; i < layer.size(); i++){ for (int j = 0; j < layer[i]->getNumVertices(); j++){ MVertex *vert = layer[i]->getVertex(j); myAssembler.fixVertex(vert, 0, _tag, 0); myAssembler.fixVertex(vert, 1, _tag, 0); } } // fix all vertices that cannot move for (unsigned int i = 0; i < v.size(); i++){ moveToStraightSidedLocation(v[i]); for (int j = 0; j < v[i]->getNumVertices(); j++){ MVertex *vert = v[i]->getVertex(j); if (vert->onWhat()->dim() < 2){ double du = 0, dv = 0; myAssembler.fixVertex(vert, 0, _tag, du); myAssembler.fixVertex(vert, 1, _tag, dv); } } } // number the other DOFs for (unsigned int i = 0; i < v.size(); i++){ for (int j = 0; j < v[i]->getNumVertices(); j++){ MVertex *vert = v[i]->getVertex(j); myAssembler.numberVertex(vert, 0, _tag); myAssembler.numberVertex(vert, 1, _tag); verticesToMove.insert(vert); } } double dx0 = smooth_metric_(v, gf, myAssembler, verticesToMove, El); double dx = dx0; Msg::Debug(" dx0 = %12.5E", dx0); int iter = 0; while(0){ double dx2 = smooth_metric_(v, gf, myAssembler, verticesToMove, El); Msg::Debug(" dx2 = %12.5E", dx2); if (fabs(dx2 - dx) < 1.e-4 * dx0)break; if (iter++ > 2)break; dx = dx2; } for (it = verticesToMove.begin(); it != verticesToMove.end(); ++it){ SPoint2 param; if ((*it)->onWhat()->dim() == 2){ reparamMeshVertexOnFace(*it, gf, param); GPoint gp = gf->point(param); (*it)->x() = gp.x(); (*it)->y() = gp.y(); (*it)->z() = gp.z(); _targetLocation[*it] = SVector3(gp.x(), gp.y(), gp.z()); } else{ SVector3 p = getTL(*it); (*it)->x() = p.x(); (*it)->y() = p.y(); (*it)->z() = p.z(); } } delete lsys; }
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)); } }
void Mesh::approximationErrorAndGradients(int iEl, double &f, std::vector<double> &gradF, double eps, simpleFunction<double> &fct) { std::vector<SPoint3> _xyz_temp; for (int iV = 0; iV < nVert(); iV++){ _xyz_temp.push_back(SPoint3( _vert[iV]->x(), _vert[iV]->y(), _vert[iV]->z())); _vert[iV]->setXYZ(_xyz[iV].x(),_xyz[iV].y(),_xyz[iV].z()); } MElement *element = _el[iEl]; f = approximationError (fct, element); // FIME // if (iEl < 1)printf("approx error elem %d = %g\n",iEl,f); int currentId = 0; // compute the size of the gradient // depends on how many dofs exist per vertex (0,1,2 or 3) for (size_t i = 0; i < element->getNumVertices(); ++i) { if (_el2FV[iEl][i] >= 0) {// some free coordinates currentId += _nPCFV[_el2FV[iEl][i]]; } } gradF.clear(); gradF.resize(currentId, 0.); currentId = 0; for (size_t i = 0; i < element->getNumVertices(); ++i) { if (_el2FV[iEl][i] >= 0) {// some free coordinates MVertex *v = element->getVertex(i); // vertex classified on a model edge if (_nPCFV[_el2FV[iEl][i]] == 1){ double t = _uvw[_el2FV[iEl][i]].x(); GEdge *ge = (GEdge*)v->onWhat(); SPoint3 p (v->x(),v->y(),v->z()); GPoint d = ge->point(t+eps); v->setXYZ(d.x(),d.y(),d.z()); double f_d = approximationError (fct, element); gradF[currentId++] = (f_d-f)/eps; if (iEl < 1)printf("df = %g\n",(f_d-f)/eps); v->setXYZ(p.x(),p.y(),p.z()); } else if (_nPCFV[_el2FV[iEl][i]] == 2){ double uu = _uvw[_el2FV[iEl][i]].x(); double vv = _uvw[_el2FV[iEl][i]].y(); GFace *gf = (GFace*)v->onWhat(); SPoint3 p (v->x(),v->y(),v->z()); GPoint d = gf->point(uu+eps,vv); v->setXYZ(d.x(),d.y(),d.z()); double f_u = approximationError (fct, element); gradF[currentId++] = (f_u-f)/eps; d = gf->point(uu,vv+eps); v->setXYZ(d.x(),d.y(),d.z()); double f_v = approximationError (fct, element); gradF[currentId++] = (f_v-f)/eps; v->setXYZ(p.x(),p.y(),p.z()); // if (iEl < 1)printf("df = %g %g\n",(f_u-f)/eps,(f_v-f)/eps); } } } for (int iV = 0; iV < nVert(); iV++) _vert[iV]->setXYZ(_xyz_temp[iV].x(),_xyz_temp[iV].y(),_xyz_temp[iV].z()); }