void exportMeshToDassault(GModel *gm, const std::string &fn, int dim) { FILE *f = fopen(fn.c_str(),"w"); int numVertices = gm->indexMeshVertices(true); std::vector<GEntity*> entities; gm->getEntities(entities); fprintf(f,"%d %d\n", numVertices, dim); for(unsigned int i = 0; i < entities.size(); i++) for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++){ MVertex *v = entities[i]->mesh_vertices[j]; if (dim == 2) fprintf(f,"%d %22.15E %22.15E\n", v->getIndex(), v->x(), v->y()); else if (dim == 3) fprintf(f,"%d %22.15E %22.15E %22.5E\n", v->getIndex(), v->x(), v->y(), v->z()); } if (dim == 2){ int nt = 0; int order = 0; for (GModel::fiter itf = gm->firstFace(); itf != gm->lastFace(); ++itf){ std::vector<MTriangle*> &tris = (*itf)->triangles; nt += tris.size(); if (tris.size())order = tris[0]->getPolynomialOrder(); } fprintf(f,"%d %d\n", nt,(order+1)*(order+2)/2); int count = 1; for (GModel::fiter itf = gm->firstFace(); itf != gm->lastFace(); ++itf){ std::vector<MTriangle*> &tris = (*itf)->triangles; for (size_t i=0;i<tris.size();i++){ MTriangle *t = tris[i]; fprintf(f,"%d ", count++); for (int j=0;j<t->getNumVertices();j++){ fprintf(f,"%d ", t->getVertex(j)->getIndex()); } fprintf(f,"\n"); } } int ne = 0; for (GModel::eiter ite = gm->firstEdge(); ite != gm->lastEdge(); ++ite){ std::vector<MLine*> &l = (*ite)->lines; ne += l.size(); } fprintf(f,"%d %d\n", ne,(order+1)); count = 1; for (GModel::eiter ite = gm->firstEdge(); ite != gm->lastEdge(); ++ite){ std::vector<MLine*> &l = (*ite)->lines; for (size_t i=0;i<l.size();i++){ MLine *t = l[i]; fprintf(f,"%d ", count++); for (int j=0;j<t->getNumVertices();j++){ fprintf(f,"%d ", t->getVertex(j)->getIndex()); } fprintf(f,"%d \n",(*ite)->tag()); } } } fclose(f); }
static void drawVerticesPerEntity(drawContext *ctx, GEntity *e) { //if(e->dim() == 2) { // if(e->cast2Edge()->getCompound()) { // if(e->cast2Edge()->getCompound() // // } //} if(CTX::instance()->mesh.points) { if(CTX::instance()->mesh.pointType) { for(unsigned int i = 0; i < e->mesh_vertices.size(); i++){ MVertex *v = e->mesh_vertices[i]; if(!v->getVisibility()) continue; 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); } ctx->drawSphere(CTX::instance()->mesh.pointSize, v->x(), v->y(), v->z(), CTX::instance()->mesh.light); } } else{ glBegin(GL_POINTS); for(unsigned int i = 0; i < e->mesh_vertices.size(); i++){ MVertex *v = e->mesh_vertices[i]; if(!v->getVisibility()) continue; 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); } glVertex3d(v->x(), v->y(), v->z()); } glEnd(); } } if(CTX::instance()->mesh.pointsNum) { int labelStep = CTX::instance()->mesh.labelSampling; if(labelStep <= 0) labelStep = 1; for(unsigned int i = 0; i < e->mesh_vertices.size(); i++) if(i % labelStep == 0) drawVertexLabel(ctx, e, e->mesh_vertices[i]); } }
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); } } }
double approximationError(simpleFunction<double> &f, MElement *element) { std::vector<double> VALS(element->getNumVertices()); for(std::size_t i = 0; i < element->getNumVertices(); i++) { MVertex *v = element->getVertex(i); VALS[i] = f(v->x(), v->y(), v->z()); } int npts; IntPt *pts; element->getIntegrationPoints(2 * element->getPolynomialOrder() + 2, &npts, &pts); double errSqr = 0.0; for(int k = 0; k < npts; k++) { const double u = pts[k].pt[0]; const double v = pts[k].pt[1]; const double w = pts[k].pt[2]; SPoint3 p; element->pnt(u, v, w, p); const double Jac = element->getJacobianDeterminant(u, v, w); const double C = element->interpolate(&VALS[0], u, v, w); const double F = f(p.x(), p.y(), p.z()); errSqr += pts[k].weight * Jac * std::pow(C - F, 2); } return std::sqrt(errSqr); }
void frameFieldBackgroundMesh2D::exportCrossField(const std::string &filename) { FILE *f = Fopen(filename.c_str(), "w"); if(!f) { Msg::Error("Could not open file '%s'", filename.c_str()); return; } fprintf(f,"View \"Cross Field\"{\n"); std::vector<double> deltas(2); deltas[0] = 0.; deltas[1] = M_PI; for (std::vector<MVertex*>::iterator it = beginvertices(); it!=endvertices(); it++) { MVertex *v = *it; double angle_current = angle(v); GPoint p = get_GPoint_from_MVertex(v); for (int i=0; i<2; i++) { Pair<SVector3, SVector3> dirs = compute_crossfield_directions(v->x(),v->y(),angle_current+deltas[i]); fprintf(f,"VP(%g,%g,%g) {%g,%g,%g};\n",p.x(),p.y(),p.z(),dirs.first()[0], dirs.first()[1], dirs.first()[2]); fprintf(f,"VP(%g,%g,%g) {%g,%g,%g};\n",p.x(),p.y(),p.z(),dirs.second()[0], dirs.second()[1], dirs.second()[2]); } } fprintf(f,"};\n"); fclose(f); }
// use real space + projection at the end static double _relocateVertex2(GFace *gf, MVertex *ver, const std::vector<MElement *> <, double tol) { SPoint3 p1(0, 0, 0); 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); p1 += SPoint3(v->x(), v->y(), v->z()); counter++; } } p1 *= 1.0 / (double)counter; SPoint3 p2(ver->x(), ver->y(), ver->z()); double worst; double xi = Maximize_Quality_Golden_Section(ver, gf, p1, p2, lt, tol, worst); SPoint3 p = p1 * (1 - xi) + p2 * xi; double initialGuess[2] = {0, 0}; GPoint pp = gf->closestPoint(p, initialGuess); if(!pp.succeeded()) return 2.0; ver->x() = pp.x(); ver->y() = pp.y(); ver->z() = pp.z(); return worst; }
static int getExtrudedVertices(MElement *ele, ExtrudeParams *ep, int j, int k, MVertexRTree &pos, std::vector<MVertex*> &verts) { double x[8], y[8], z[8]; int n = ele->getNumVertices(); for(int p = 0; p < n; p++){ MVertex *v = ele->getVertex(p); x[p] = x[p + n] = v->x(); y[p] = y[p + n] = v->y(); z[p] = z[p + n] = v->z(); } for(int p = 0; p < n; p++){ ep->Extrude(j, k, x[p], y[p], z[p]); ep->Extrude(j, k + 1, x[p + n], y[p + n], z[p + n]); } for(int p = 0; p < 2 * n; p++){ MVertex *tmp = pos.find(x[p], y[p], z[p]); if(!tmp) Msg::Error("Could not find extruded vertex (%.16g, %.16g, %.16g)", x[p], y[p], z[p]); else verts.push_back(tmp); } return verts.size(); }
void carveHole(std::vector<T*> &elements, double distance, ANNkd_tree *kdtree) { // delete all elements that have at least one vertex closer than // 'distance' from the carving surface vertices ANNidxArray index = new ANNidx[1]; ANNdistArray dist = new ANNdist[1]; std::vector<T*> temp; for(unsigned int i = 0; i < elements.size(); i++){ for(int j = 0; j < elements[i]->getNumVertices(); j++){ MVertex *v = elements[i]->getVertex(j); double xyz[3] = {v->x(), v->y(), v->z()}; kdtree->annkSearch(xyz, 1, index, dist); double d = sqrt(dist[0]); if(d < distance){ delete elements[i]; break; } else if(j == elements[i]->getNumVertices() - 1){ temp.push_back(elements[i]); } } } elements = temp; delete [] index; delete [] dist; }
void highOrderTools::ensureMinimumDistorsion(MElement *e, double threshold) { double dist = e->distoShapeMeasure(); if (dist > threshold) return; double a1 = 0., a2 = 1.0, x[1000][3], X[1000][3] ; for(int i = 0; i < e->getNumVertices(); i++){ MVertex *v = e->getVertex(i); x[i][0] = v->x(); x[i][1] = v->y(); x[i][2] = v->z(); std::map<MVertex*,SVector3>::const_iterator it = _straightSidedLocation.find(v); if (it != _straightSidedLocation.end()){ X[i][0] = it->second.x(); X[i][1] = it->second.y(); X[i][2] = it->second.z(); } else { X[i][0] = v->x(); X[i][1] = v->y(); X[i][2] = v->z(); } } // a == 0 -> straight // a == 1 -> curved int ITER = 1; while(1){ double a = 0.5*(a1+a2); if (ITER > 10) a = 0.; for(int i = 0; i < e->getNumVertices(); i++){ MVertex *v = e->getVertex(i); v->x() = a * x[i][0] + (1.-a) * X[i][0]; v->y() = a * x[i][1] + (1.-a) * X[i][1]; v->z() = a * x[i][2] + (1.-a) * X[i][2]; } double dist = e->distoShapeMeasure(); // printf("a = %g dist = %g\n",a,dist); // getchar(); if (dist > 0 && fabs(dist-threshold) < .05)break; if (dist < threshold)a2 = a; else a1 = a; if (a > .99 || a < .01) break; ++ITER; } // printf("element done\n"); }
void highOrderTools::moveToStraightSidedLocation(MElement *e) const { for(int i = 0; i < e->getNumVertices(); i++){ MVertex *v = e->getVertex(i); std::map<MVertex*,SVector3>::const_iterator it = _straightSidedLocation.find(v); if (it != _straightSidedLocation.end()){ v->x() = it->second.x(); v->y() = it->second.y(); v->z() = it->second.z(); } } }
int GModel::writeMAIL(const std::string &name, bool saveAll, double scalingFactor) { // CEA triangulation (.mail format) for Eric Darrigrand. Note that // we currently don't save the edges of the triangulation (the last // part of the file). FILE *fp = Fopen(name.c_str(), "w"); if(!fp){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } if(noPhysicalGroups()) saveAll = true; int numVertices = indexMeshVertices(saveAll), numTriangles = 0; for(fiter it = firstFace(); it != lastFace(); ++it) if(saveAll || (*it)->physicals.size()) numTriangles += (*it)->triangles.size(); fprintf(fp, " %d %d\n", numVertices, numTriangles); std::vector<GEntity*> entities; getEntities(entities); for(unsigned int i = 0; i < entities.size(); i++){ for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++){ MVertex *v = entities[i]->mesh_vertices[j]; fprintf(fp, " %19.10E %19.10E %19.10E\n", v->x() * scalingFactor, v->y() * scalingFactor, v->z() * scalingFactor); } } for(fiter it = firstFace(); it != lastFace(); ++it){ if(saveAll || (*it)->physicals.size()){ for(unsigned int i = 0; i < (*it)->triangles.size(); i++){ MTriangle *t = (*it)->triangles[i]; fprintf(fp, " %d %d %d\n", t->getVertex(0)->getIndex(), t->getVertex(1)->getIndex(), t->getVertex(2)->getIndex()); } } } // TODO write edges (with signs) for(fiter it = firstFace(); it != lastFace(); ++it){ if(saveAll || (*it)->physicals.size()){ for(unsigned int i = 0; i < (*it)->triangles.size(); i++){ //MTriangle *t = (*it)->triangles[i]; fprintf(fp, " %d %d %d\n", 0, 0, 0); } } } fclose(fp); return 1; }
void Centerline::importFile(std::string fileName) { current = GModel::current(); std::vector<GFace*> currentFaces(current->firstFace(), current->lastFace()); for (unsigned int i = 0; i < currentFaces.size(); i++){ GFace *gf = currentFaces[i]; if (gf->geomType() == GEntity::DiscreteSurface){ for(unsigned int j = 0; j < gf->triangles.size(); j++) triangles.push_back(gf->triangles[j]); if (is_cut){ gf->triangles.clear(); gf->deleteVertexArrays(); current->remove(gf); } } } if(triangles.empty()){ Msg::Error("Current GModel has no triangles ..."); return; } mod = new GModel(); mod->load(fileName); mod->removeDuplicateMeshVertices(1.e-8); current->setAsCurrent(); current->setVisibility(1); int maxN = 0.0; std::vector<GEdge*> modEdges(mod->firstEdge(), mod->lastEdge()); MVertex *vin = modEdges[0]->lines[0]->getVertex(0); ptin = SPoint3(vin->x(), vin->y(), vin->z()); for (unsigned int i = 0; i < modEdges.size(); i++){ GEdge *ge = modEdges[i]; for(unsigned int j = 0; j < ge->lines.size(); j++){ MLine *l = ge->lines[j]; MVertex *v0 = l->getVertex(0); MVertex *v1 = l->getVertex(1); std::map<MVertex*, int>::iterator it0 = colorp.find(v0); std::map<MVertex*, int>::iterator it1 = colorp.find(v1); if (it0 == colorp.end() || it1 == colorp.end()){ lines.push_back(l); colorl.insert(std::make_pair(l, ge->tag())); maxN = std::max(maxN, ge->tag()); } if (it0 == colorp.end()) colorp.insert(std::make_pair(v0, ge->tag())); if (it1 == colorp.end()) colorp.insert(std::make_pair(v1, ge->tag())); } } createBranches(maxN); }
void GEdge::relocateMeshVertices() { for(unsigned int i = 0; i < mesh_vertices.size(); i++){ MVertex *v = mesh_vertices[i]; double u0 = 0; if(v->getParameter(0, u0)){ GPoint p = point(u0); v->x() = p.x(); v->y() = p.y(); v->z() = p.z(); } } }
void print_nodal_info(string filename, map<MVertex*, T> &mapp) { ofstream out(filename.c_str()); out << "View \"\"{" << endl; for (typename map<MVertex*, T>::iterator it = mapp.begin();it!=mapp.end();it++){ MVertex *v = it->first; out << "SP( " << v->x() << "," << v->y() << "," << v->z() << "){" << it->second << "};" << endl;; } out << "};" << endl; out.close(); }
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); } } } }
void print_nodal_info(const std::string &filename, std::map<MVertex *, T> const &map) { std::ofstream out(filename.c_str()); out << "View \"\"{" << std::endl; for(typename std::map<MVertex *, T>::const_iterator it = map.begin(); it != map.end(); it++) { MVertex *v = it->first; out << "SP( " << v->x() << "," << v->y() << "," << v->z() << "){" << it->second << "};" << std::endl; } out << "};" << std::endl; out.close(); }
void Centerline::buildKdTree() { FILE * f = Fopen("myPOINTS.pos","w"); fprintf(f, "View \"\"{\n"); int nbPL = 3; //10 points per line //int nbNodes = (lines.size()+1) + (nbPL*lines.size()); int nbNodes = (colorp.size()) + (nbPL*lines.size()); ANNpointArray nodes = annAllocPts(nbNodes, 3); int ind = 0; std::map<MVertex*, int>::iterator itp = colorp.begin(); while (itp != colorp.end()){ MVertex *v = itp->first; nodes[ind][0] = v->x(); nodes[ind][1] = v->y(); nodes[ind][2] = v->z(); itp++; ind++; } for(unsigned int k = 0; k < lines.size(); ++k){ MVertex *v0 = lines[k]->getVertex(0); MVertex *v1 = lines[k]->getVertex(1); SVector3 P0(v0->x(),v0->y(), v0->z()); SVector3 P1(v1->x(),v1->y(), v1->z()); for (int j= 1; j < nbPL+1; j++){ double inc = (double)j/(double)(nbPL+1); SVector3 Pj = P0+inc*(P1-P0); nodes[ind][0] = Pj.x(); nodes[ind][1] = Pj.y(); nodes[ind][2] = Pj.z(); ind++; } } kdtree = new ANNkd_tree(nodes, nbNodes, 3); for(int i = 0; i < nbNodes; ++i){ fprintf(f, "SP(%g,%g,%g){%g};\n", nodes[i][0], nodes[i][1],nodes[i][2],1.0); } fprintf(f,"};\n"); fclose(f); }
void MSubPoint::getIntegrationPoints(int pOrder, int *npts, IntPt **pts) { // invariable regardless of the order if(!_pts) { if(!_orig) return; _pts = new IntPt[1]; // work in the parametric space of the parent element MVertex *vi = getVertex(0); double v_xyz[3] = {vi->x(), vi->y(), vi->z()}; double v_uvw[3]; _orig->xyz2uvw(v_xyz, v_uvw); double jac[3][3]; double origJac = _orig->getJacobian(v_uvw[0], v_uvw[1], v_uvw[2], jac); _pts[0].pt[0] = v_uvw[0]; _pts[0].pt[1] = v_uvw[1]; _pts[0].pt[2] = v_uvw[2]; _pts[0].weight = 1./origJac; } *npts = 1; *pts = _pts; }
void Centerline::distanceToSurface() { Msg::Info("Centerline: computing distance to surface mesh "); //COMPUTE WITH REVERSE ANN TREE (SURFACE POINTS IN TREE) std::set<MVertex*> allVS; for(unsigned int j = 0; j < triangles.size(); j++) for(int k = 0; k<3; k++) allVS.insert(triangles[j]->getVertex(k)); int nbSNodes = allVS.size(); ANNpointArray nodesR = annAllocPts(nbSNodes, 3); vertices.resize(nbSNodes); int ind = 0; std::set<MVertex*>::iterator itp = allVS.begin(); while (itp != allVS.end()){ MVertex *v = *itp; nodesR[ind][0] = v->x(); nodesR[ind][1] = v->y(); nodesR[ind][2] = v->z(); vertices[ind] = v; itp++; ind++; } kdtreeR = new ANNkd_tree(nodesR, nbSNodes, 3); for(unsigned int i = 0; i < lines.size(); i++){ MLine *l = lines[i]; MVertex *v1 = l->getVertex(0); MVertex *v2 = l->getVertex(1); double midp[3] = {0.5*(v1->x()+v2->x()), 0.5*(v1->y()+v1->y()),0.5*(v1->z()+v2->z())}; ANNidx index[1]; ANNdist dist[1]; kdtreeR->annkSearch(midp, 1, index, dist); double minRad = sqrt(dist[0]); radiusl.insert(std::make_pair(lines[i], minRad)); } }
void GMSH_DistancePlugin::printView(std::vector<GEntity*> _entities, std::map<MVertex*, double > _distance_map) { _fileName = DistanceOptions_String[0].def; _minScale = (double) DistanceOptions_Number[4].def; _maxScale = (double) DistanceOptions_Number[5].def; double minDist=1.e4; double maxDist=0.0; for (std::map<MVertex*,double >::iterator itv=_distance_map.begin(); itv != _distance_map.end(); ++itv){ double dist = itv->second; if (dist>maxDist) maxDist = dist; if (dist<minDist) minDist = dist; itv->second = dist; } Msg::Info("Writing %s", _fileName.c_str()); FILE *fName = Fopen(_fileName.c_str(),"w"); fprintf(fName, "View \"distance \"{\n"); for (unsigned int ii=0; ii<_entities.size(); ii++) { if (_entities[ii]->dim() == _maxDim) { for (unsigned int i=0; i<_entities[ii]->getNumMeshElements(); i++) { MElement *e = _entities[ii]->getMeshElement(i); int numNodes = e->getNumVertices(); if (e->getNumChildren()) numNodes = e->getNumChildren() * e->getChild(0)->getNumVertices(); std::vector<double> x(numNodes), y(numNodes), z(numNodes); std::vector<double> *out = _data->incrementList(1, e->getType(), numNodes); std::vector<MVertex*> nods; if (!e->getNumChildren()) for(int i = 0; i < numNodes; i++) nods.push_back(e->getVertex(i)); else for(int i = 0; i < e->getNumChildren(); i++) for(int j = 0; j < e->getChild(i)->getNumVertices(); j++) nods.push_back(e->getChild(i)->getVertex(j)); for (int nod = 0; nod < numNodes; nod++) out->push_back((nods[nod])->x()); for (int nod = 0; nod < numNodes; nod++) out->push_back((nods[nod])->y()); for (int nod = 0; nod < numNodes; nod++) out->push_back((nods[nod])->z()); if (_maxDim == 2) switch (numNodes) { case 2: fprintf(fName,"SL("); break; case 3: fprintf(fName,"ST("); break; case 4: fprintf(fName,"SQ("); break; default: Msg::Error("Error in Plugin 'Distance' (numNodes=%d)", numNodes); break; } else if (_maxDim == 3) switch (numNodes) { case 4: fprintf(fName,"SS("); break; case 8: fprintf(fName,"SH("); break; case 6: fprintf(fName,"SI("); break; case 5: fprintf(fName,"SY("); break; default: Msg::Error("Error in Plugin 'Distance' (numNodes=%d)", numNodes); break; } std::vector<double> dist; for (int j=0; j<numNodes; j++) { MVertex *v = nods[j]; if (j) fprintf(fName, ",%.16g,%.16g,%.16g", v->x(), v->y(), v->z()); else fprintf(fName, "%.16g,%.16g,%.16g", v->x(), v->y(), v->z()); std::map<MVertex*, double>::iterator it = _distance_map.find(v); dist.push_back(it->second); } fprintf(fName,"){"); for (unsigned int i=0; i<dist.size(); i++) { if (_minScale>0 && _maxScale>0) dist[i] = _minScale + ((dist[i] - minDist) / (maxDist - minDist)) * (_maxScale - _minScale); else if (_minScale>0 && _maxScale<0) dist[i] = _minScale + dist[i]; out->push_back(dist[i]); if (i) fprintf(fName, ",%.16g", dist[i]); else fprintf(fName, "%.16g", dist[i]); } fprintf(fName,"};\n"); } } } fprintf(fName,"};\n"); fclose(fName); }
PView *GMSH_DistancePlugin::execute(PView *v) { int id_pt = (int) DistanceOptions_Number[0].def; int id_line = (int) DistanceOptions_Number[1].def; int id_face = (int) DistanceOptions_Number[2].def; double type = (double) DistanceOptions_Number[3].def; int ortho = (int) DistanceOptions_Number[6].def; PView *view = new PView(); _data = getDataList(view); #if defined(HAVE_SOLVER) #if defined(HAVE_TAUCS) linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>; #else linearSystemCSRGmm<double> *lsys = new linearSystemCSRGmm<double>; lsys->setNoisy(1); lsys->setGmres(1); lsys->setPrec(5.e-8); #endif dofManager<double> * dofView = new dofManager<double>(lsys); #endif std::vector<GEntity*> _entities; GModel::current()->getEntities(_entities); if (!_entities.size() || !_entities[_entities.size()-1]->getMeshElement(0)) { Msg::Error("This plugin needs a mesh !"); return view; } GEntity* ge = _entities[_entities.size()-1]; int integrationPointTetra[2] = {0,0}; int numnodes = 0; for (unsigned int i = 0; i < _entities.size()-1; i++) numnodes += _entities[i]->mesh_vertices.size(); int totNodes = numnodes + _entities[_entities.size()-1]->mesh_vertices.size(); int order = ge->getMeshElement(0)->getPolynomialOrder(); int totNumNodes = totNodes + ge->getNumMeshElements()*integrationPointTetra[order-1]; std::vector<SPoint3> pts; std::vector<double> distances; std::vector<MVertex* > pt2Vertex; pts.clear(); distances.clear(); pt2Vertex.clear(); pts.reserve(totNumNodes); distances.reserve(totNumNodes); pt2Vertex.reserve(totNumNodes); std::map<MVertex*,double> _distanceE_map; std::map<MVertex*,int> _isInYarn_map; std::vector<int> index; std::vector<double> distancesE; std::vector<double> distances2; std::vector<double> distancesE2; std::vector<int> isInYarn; std::vector<int> isInYarn2; std::vector<SPoint3> closePts; std::vector<SPoint3> closePts2; for (int i=0; i<totNumNodes; i++) { distances.push_back(1.e22); } int k = 0; for (unsigned int i=0; i<_entities.size(); i++){ GEntity* ge = _entities[i]; _maxDim = std::max(_maxDim, ge->dim()); for (unsigned int j=0; j<ge->mesh_vertices.size(); j++) { MVertex *v = ge->mesh_vertices[j]; pts.push_back(SPoint3(v->x(), v->y(), v->z())); _distance_map.insert(std::make_pair(v, 0.0)); /* TO DO (by AM) SPoint3 p_empty(); _closePts_map.insert(std::make_pair(v, p_empty)); */ pt2Vertex[k] = v; k++; } } // Compute geometrical distance to mesh boundaries //------------------------------------------------------ if (type < 0.0 ) { bool existEntity = false; for (unsigned int i=0; i<_entities.size(); i++) { GEntity* g2 = _entities[i]; int gDim = g2->dim(); std::vector<int> phys = g2->getPhysicalEntities(); bool computeForEntity = false; for(unsigned int k = 0; k<phys.size(); k++) { int tagp = phys[k]; if (id_pt == 0 && id_line == 0 && id_face == 0 && gDim == _maxDim - 1) computeForEntity = true; else if ((tagp == id_pt && gDim == 0) || (tagp == id_line && gDim == 1) || (tagp == id_face && gDim == 2)) computeForEntity = true; } if (computeForEntity) { existEntity = true; for (unsigned int k = 0; k < g2->getNumMeshElements(); k++) { std::vector<double> iDistances; std::vector<SPoint3> iClosePts; std::vector<double> iDistancesE; std::vector<int> iIsInYarn; MElement *e = g2->getMeshElement(k); MVertex *v1 = e->getVertex(0); MVertex *v2 = e->getVertex(1); SPoint3 p1(v1->x(), v1->y(), v1->z()); SPoint3 p2(v2->x(), v2->y(), v2->z()); if ((e->getNumVertices() == 2 && order == 1) || (e->getNumVertices() == 3 && order == 2)) { signedDistancesPointsLine(iDistances, iClosePts, pts, p1, p2); } else if ((e->getNumVertices() == 3 && order == 1) || (e->getNumVertices() == 6 && order == 2)) { MVertex *v3 = e->getVertex(2); SPoint3 p3 (v3->x(),v3->y(),v3->z()); signedDistancesPointsTriangle(iDistances, iClosePts, pts, p1, p2, p3); } for (unsigned int kk=0; kk<pts.size(); kk++) { if (std::abs(iDistances[kk]) < distances[kk]) { distances[kk] = std::abs(iDistances[kk]); MVertex *v = pt2Vertex[kk]; _distance_map[v] = distances[kk]; /* TO DO (by AM) _closePts_map[v] = iClosePts[kk]; */ } } } } } if (!existEntity){ if (id_pt != 0) Msg::Error("The Physical Point does not exist !"); if (id_line != 0) Msg::Error("The Physical Line does not exist !"); if (id_face != 0) Msg::Error("The Physical Surface does not exist !"); return view; } printView(_entities, _distance_map); /* TO DO (by AM) printView(_entities, _closePts_map); */ } // Compute PDE for distance function //----------------------------------- else if (type > 0.0) { #if defined(HAVE_SOLVER) bool existEntity = false; SBoundingBox3d bbox; for(unsigned int i = 0; i < _entities.size(); i++){ GEntity* ge = _entities[i]; int gDim = ge->dim(); bool fixForEntity = false; std::vector<int> phys = ge->getPhysicalEntities(); for(unsigned int k = 0; k < phys.size(); k++) { int tagp = phys[k]; if (id_pt == 0 && id_line == 0 && id_face == 0 && gDim == _maxDim - 1) fixForEntity = true; else if ((tagp == id_pt && gDim == 0) || (tagp == id_line && gDim == 1) || (tagp == id_face && gDim == 2) ) fixForEntity = true; } if (fixForEntity) { existEntity = true; for (unsigned int i = 0; i < ge->getNumMeshElements(); ++i) { MElement *t = ge->getMeshElement(i); for (int k=0; k<t->getNumVertices(); k++) { MVertex *v = t->getVertex(k); dofView->fixVertex(v, 0, 1, 0.); bbox += SPoint3(v->x(), v->y(), v->z()); } } } } if (!existEntity){ if (id_pt != 0) Msg::Error("The Physical Point does not exist !"); if (id_line != 0) Msg::Error("The Physical Line does not exist !"); if (id_face != 0) Msg::Error("The Physical Surface does not exist !"); return view; } std::vector<MElement *> allElems; for(unsigned int ii = 0; ii < _entities.size(); ii++){ if(_entities[ii]->dim() == _maxDim) { GEntity *ge = _entities[ii]; for(unsigned int i = 0; i < ge->getNumMeshElements(); ++i) { MElement *t = ge->getMeshElement(i); allElems.push_back(t); for (int k = 0; k < t->getNumVertices(); k++) dofView->numberVertex(t->getVertex(k), 0, 1); } } } double L = norm(SVector3(bbox.max(), bbox.min())); double mu = type*L; simpleFunction<double> DIFF(mu*mu), ONE(1.0); distanceTerm distance(GModel::current(), 1, &DIFF, &ONE); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ SElement se((*it)); distance.addToMatrix(*dofView, &se); } groupOfElements gr(allElems); distance.addToRightHandSide(*dofView, gr); Msg::Info("Distance Computation: Assembly done"); lsys->systemSolve(); Msg::Info("Distance Computation: System solved"); for (std::map<MVertex*,double >::iterator itv = _distance_map.begin(); itv != _distance_map.end() ; ++itv) { MVertex *v = itv->first; double value; dofView->getDofValue(v, 0, 1, value); value = std::min(0.9999, value); double dist = -mu * log(1. - value); itv->second = dist; } printView(_entities, _distance_map); #endif } _data->setName("distance"); _data->Time.push_back(0); _data->setFileName(_fileName.c_str()); _data->finalize(); // compute also orthogonal vector to distance field // A Uortho = -C DIST //------------------------------------------------ if (ortho > 0) { #if defined(HAVE_SOLVER) #ifdef HAVE_TAUCS linearSystemCSRTaucs<double> *lsys2 = new linearSystemCSRTaucs<double>; #else linearSystemCSRGmm<double> *lsys2 = new linearSystemCSRGmm<double>; lsys->setNoisy(1); lsys->setGmres(1); lsys->setPrec(5.e-8); #endif dofManager<double> myAssembler(lsys2); simpleFunction<double> ONE(1.0); double dMax = 1.0; //EMI TO CHANGE std::vector<MElement *> allElems; for(unsigned int ii = 0; ii < _entities.size(); ii++){ if (_entities[ii]->dim() == _maxDim) { GEntity *ge = _entities[ii]; for (unsigned int i=0; i<ge->getNumMeshElements(); ++i) { MElement *t = ge->getMeshElement(i); double vMean = 0.0; for (int k = 0; k < t->getNumVertices(); k++) { std::map<MVertex*, double>::iterator it = _distance_map.find(t->getVertex(k)); vMean += it->second; } vMean /= t->getNumVertices(); if (vMean < dMax) allElems.push_back(ge->getMeshElement(i)); } } } int mid = (int)floor(allElems.size() / 2.); MElement *e = allElems[mid]; MVertex *vFIX = e->getVertex(0); myAssembler.fixVertex(vFIX, 0, 1, 0.0); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ MElement *t = *it; for(int k = 0; k < t->getNumVertices(); k++) myAssembler.numberVertex(t->getVertex(k), 0, 1); } orthogonalTerm *ortho; ortho = new orthogonalTerm(GModel::current(), 1, &ONE, &_distance_map); // if (type < 0) // ortho = new orthogonalTerm(GModel::current(), 1, &ONE, view); // else // ortho = new orthogonalTerm(GModel::current(), 1, &ONE, dofView); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ SElement se((*it)); ortho->addToMatrix(myAssembler, &se); } groupOfElements gr(allElems); ortho->addToRightHandSide(myAssembler, gr); Msg::Info("Orthogonal Computation: Assembly done"); lsys2->systemSolve(); Msg::Info("Orthogonal Computation: System solved"); PView *view2 = new PView(); PViewDataList *data2 = getDataList(view2); data2->setName("ortogonal field"); Msg::Info("Writing orthogonal.pos"); FILE * f5 = Fopen("orthogonal.pos","w"); fprintf(f5,"View \"orthogonal\"{\n"); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ MElement *e = *it; int numNodes = e->getNumVertices(); if (e->getType() == TYPE_POLYG) numNodes = e->getNumChildren() * e->getChild(0)->getNumVertices(); std::vector<double> x(numNodes), y(numNodes), z(numNodes); std::vector<double> *out2 = data2->incrementList(1, e->getType(), numNodes); std::vector<MVertex*> nods; std::vector<double> orth; if(!e->getNumChildren()) for(int i=0; i<numNodes; i++) nods.push_back(e->getVertex(i)); else for(int i = 0; i < e->getNumChildren(); i++) for(int j = 0; j < e->getChild(i)->getNumVertices(); j++) nods.push_back(e->getChild(i)->getVertex(j)); for(int nod = 0; nod < numNodes; nod++) out2->push_back((nods[nod])->x()); for(int nod = 0; nod < numNodes; nod++) out2->push_back((nods[nod])->y()); for(int nod = 0; nod < numNodes; nod++) out2->push_back((nods[nod])->z()); if (_maxDim == 2) switch (numNodes) { case 2: fprintf(f5,"SL("); break; case 3: fprintf(f5,"ST("); break; case 4: fprintf(f5,"SQ("); break; default: Msg::Fatal("Error in Plugin 'Distance' (numNodes=%g).",numNodes); break; } else if (_maxDim == 3) switch (numNodes) { case 4: fprintf(f5,"SS("); break; case 8: fprintf(f5,"SH("); break; case 6: fprintf(f5,"SI("); break; case 5: fprintf(f5,"SY("); break; default: Msg::Fatal("Error in Plugin 'Distance' (numNodes=%g).",numNodes); break; } for (int j=0; j<numNodes; j++) { MVertex *v = nods[j]; if (j) fprintf(f5, ",%g,%g,%g", v->x(), v->y(), v->z()); else fprintf(f5, "%g,%g,%g", v->x(), v->y(), v->z()); double value; myAssembler.getDofValue(v, 0, 1, value); orth.push_back(value); } fprintf(f5,"){"); for (unsigned int i=0; i<orth.size(); i++) { out2->push_back(orth[i]); if (i) fprintf(f5,",%g", orth[i]); else fprintf(f5,"%g", orth[i]); } fprintf(f5,"};\n"); } fprintf(f5,"};\n"); fclose(f5); lsys->clear(); lsys2->clear(); data2->Time.push_back(0); data2->setFileName("orthogonal.pos"); data2->finalize(); #endif } return view; }
// This function meshes the top surface of a QuadToTri extrusion. It returns 0 if it is given a // non-quadToTri extrusion or if it fails. // Args: // 'GFace *to' is the top surface to mesh, 'from' is the source surface, 'pos' is a std::set // of vertex positions for the top surface. int MeshQuadToTriTopSurface( GFace *from, GFace *to, std::set<MVertex*, MVertexLessThanLexicographic> &pos ) { if( !to->meshAttributes.extrude || !to->meshAttributes.extrude->mesh.QuadToTri ) return 0; // if the source is all triangles, then just let this function is not needed. Return 1. if( from->triangles.size() && !from->quadrangles.size() ) return 1; // in weird case of NO quads and NO tri if( !from->triangles.size() && !from->quadrangles.size() ) return 0; ExtrudeParams *ep = to->meshAttributes.extrude; if( !ep || !ep->mesh.ExtrudeMesh || !(ep->geo.Mode == COPIED_ENTITY) ){ Msg::Error("In MeshQuadToTriTopSurface(), incomplete or no " "extrude information for top face %d.", to->tag() ); return 0; } // is this a quadtri extrusion with added vertices? bool is_addverts = false; if( ep && (ep->mesh.QuadToTri == QUADTRI_ADDVERTS_1 || ep->mesh.QuadToTri == QUADTRI_ADDVERTS_1_RECOMB) ) is_addverts = true; // execute this section if // IF this is a 'no new vertices' quadToTri, mesh the surfaces according to this modified // least point value method: if a 3 boundary point quad, draw diagonals from middle corner toward // interior. If a a 2- or 1- point boundary quad, draw toward lowest pointer number NOT on boundary. // All interior quad, draw diagonal to vertex with lowest pointer number. if( !is_addverts ){ std::set<MVertex*, MVertexLessThanLexicographic> pos_src_edge; QuadToTriInsertFaceEdgeVertices(from, pos_src_edge); std::set<MVertex*, MVertexLessThanLexicographic>::iterator itp; // loop through each element source quadrangle and extrude for(unsigned int i = 0; i < from->quadrangles.size(); i++){ std::vector<MVertex*> verts; for(int j = 0; j < from->quadrangles[i]->getNumVertices(); j++){ MVertex *v = from->quadrangles[i]->getVertex(j); MVertex tmp(v->x(), v->y(), v->z(), 0, -1); ExtrudeParams *ep = to->meshAttributes.extrude; ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1], tmp.x(), tmp.y(), tmp.z()); itp = pos.find(&tmp); if(itp == pos.end()){ // FIXME: workaround Msg::Info("Linear search for (%.16g, %.16g, %.16g)", tmp.x(), tmp.y(), tmp.z()); itp = tmp.linearSearch(pos); } if(itp == pos.end()) { Msg::Error("In MeshQuadToTriTopSurface(), Could not find " "extruded vertex (%.16g, %.16g, %.16g) in surface %d", tmp.x(), tmp.y(), tmp.z(), to->tag()); to->triangles.reserve(to->triangles.size()+1); return 0; } verts.push_back(*itp); } if( verts.size() != 4 ){ Msg::Error("During mesh of QuadToTri surface %d, %d vertices found " "in quad of source surface %d.", to->tag(), verts.size(), from->tag() ); return 0; } // make the element MElement *element = from->quadrangles[i]; // count vertices that are on a boundary edge int edge_verts_count = 0; //int skip_index = 0; int bnd_indices[4]; for( int p = 0; p < element->getNumVertices(); p++ ){ if( pos_src_edge.find( element->getVertex(p) ) != pos_src_edge.end() ){ edge_verts_count++; bnd_indices[p] = 1; } else{ //skip_index = p; bnd_indices[p] = 0; } } // Apply modified lowest vertex pointer diagonalization int low_index = -1; if( edge_verts_count == 3 || edge_verts_count == 2 || edge_verts_count == 1 ){ for( int p = 0; p < 4; p++ ){ if( !bnd_indices[p] && verts[p] != element->getVertex(p) ){ if( low_index < 0 ) low_index = p; else if( verts[p] < verts[low_index] ) low_index = p; } } if( low_index < 0 ) // what if they are all degenerate? Avoid the out-of-bounds error. low_index = 0; } // lowest possible vertex pointer, regardless of if on edge or not else if( edge_verts_count == 4 || edge_verts_count == 0 ) low_index = getIndexForLowestVertexPointer(verts); addTriangle( verts[low_index],verts[(low_index+1)%verts.size()], verts[(low_index+2)%verts.size()],to); addTriangle( verts[low_index],verts[(low_index+2)%verts.size()], verts[(low_index+3)%verts.size()],to); } return 1; } // AFTER THIS POINT IN FUNCTION, CODE IS ALL FOR 'ADD INTERNAL VERTEX' EXTRUSIONS (Less restrictive). // if source face is unstructured, can try to make the top mesh a little neater GFace *root_source = findRootSourceFaceForFace( from ); ExtrudeParams *ep_src = root_source->meshAttributes.extrude; bool struct_root = false; if( root_source && ( (ep_src && ep_src->mesh.ExtrudeMesh && ep_src->geo.Mode == EXTRUDED_ENTITY) || root_source->meshAttributes.method == MESH_TRANSFINITE ) ) struct_root = true; if( !struct_root && MeshQuadToTriTopUnstructured(from, to, pos) ) return 1; // And top surface for the 'added internal vertex' method can be meshed quite easily else{ std::set<MVertex *, MVertexLessThanLexicographic >::iterator itp; // loop through each element source quadrangle and extrude for(unsigned int i = 0; i < from->quadrangles.size(); i++){ std::vector<MVertex*> verts; for(int j = 0; j < from->quadrangles[i]->getNumVertices(); j++){ MVertex *v = from->quadrangles[i]->getVertex(j); MVertex tmp(v->x(), v->y(), v->z(), 0, -1); ExtrudeParams *ep = to->meshAttributes.extrude; ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1], tmp.x(), tmp.y(), tmp.z()); itp = pos.find(&tmp); if(itp == pos.end()){ // FIXME: workaround Msg::Info("Linear search for (%.16g, %.16g, %.16g)", tmp.x(), tmp.y(), tmp.z()); itp = tmp.linearSearch(pos); } if(itp == pos.end()) { Msg::Error("In MeshQuadToTriTopSurface(), Could not find " "extruded vertex (%.16g, %.16g, %.16g) in surface %d", tmp.x(), tmp.y(), tmp.z(), to->tag()); to->triangles.reserve(to->triangles.size()+1); return 0; } verts.push_back(*itp); } if( verts.size() != 4 ){ Msg::Error("During mesh of QuadToTri surface %d, %d vertices found " "in quad of source surface %d.", to->tag(), verts.size(), from->tag() ); return 0; } // make the elements addTriangle( verts[0],verts[2], verts[3],to); addTriangle( verts[0],verts[1], verts[2],to); } return 1; } return 0; }
// this function specifically meshes a quadToTri top in an unstructured way // return 1 if success, return 0 if failed. // Added 2010-12-20 static int MeshQuadToTriTopUnstructured(GFace *from, GFace *to, std::set<MVertex*, MVertexLessThanLexicographic> &pos) { // if the source is all triangles, then just return 1. if( from->triangles.size() && !from->quadrangles.size() ) return 1; if( !to->meshAttributes.extrude || !to->meshAttributes.extrude->mesh.QuadToTri ) return 0; // in weird case of NO quads and NO tri if( !from->triangles.size() && !from->quadrangles.size() ) return 0; // make set of source edge vertices std::set<MVertex*, MVertexLessThanLexicographic> pos_src_edge; QuadToTriInsertFaceEdgeVertices(from, pos_src_edge); // Loop through all the quads and make the triangles with diagonals running // in a selected direction. to->triangles.reserve(to->triangles.size()+from->quadrangles.size()*2); std::set<MVertex*, MVertexLessThanLexicographic>::iterator itp; for(unsigned int i = 0; i < from->quadrangles.size(); i++){ std::vector<MVertex*> verts; for(int j = 0; j < from->quadrangles[i]->getNumVertices(); j++){ MVertex *v = from->quadrangles[i]->getVertex(j); MVertex tmp(v->x(), v->y(), v->z(), 0, -1); ExtrudeParams *ep = to->meshAttributes.extrude; ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1], tmp.x(), tmp.y(), tmp.z()); itp = pos.find(&tmp); if(itp == pos.end()){ // FIXME: workaround Msg::Info("Linear search for (%.16g, %.16g, %.16g)", tmp.x(), tmp.y(), tmp.z()); itp = tmp.linearSearch(pos); } if(itp == pos.end()) { Msg::Error("Could not find extruded vertex (%.16g, %.16g, %.16g) in surface %d", tmp.x(), tmp.y(), tmp.z(), to->tag()); to->triangles.reserve(to->triangles.size()+1); return 0; } verts.push_back(*itp); } if( verts.size() != 4 ){ Msg::Error("During mesh of QuadToTri surface %d, %d vertices found " "in quad of source surface %d.", to->tag(), verts.size(), from->tag() ); return 0; } // draw other diagonals to minimize difference in average edge length with diagonal length, in quadrature double mag_sq_ave = 0.0; for( int p = 0; p < 4; p++ ){ int d_leg = verts[p]->distance(verts[(p+1)%4]); mag_sq_ave += d_leg*d_leg; } mag_sq_ave /= 4; double d1 = verts[0]->distance(verts[2]); double d2 = verts[1]->distance(verts[3]); if(fabs(d1*d1-mag_sq_ave) <= fabs(d2*d2-mag_sq_ave) ){ addTriangle(verts[0],verts[1],verts[2],to); addTriangle(verts[0],verts[2],verts[3],to); } else{ addTriangle(verts[1],verts[2],verts[3],to); addTriangle(verts[1],verts[3],verts[0],to); } } return 1; }
int GModel::readMED(const std::string &name) { med_idt fid = MEDouvrir((char*)name.c_str(), MED_LECTURE); if(fid < 0) { Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } med_int v[3], vf[3]; MEDversionDonner(&v[0], &v[1], &v[2]); MEDversionLire(fid, &vf[0], &vf[1], &vf[2]); Msg::Info("Reading MED file V%d.%d.%d using MED library V%d.%d.%d", vf[0], vf[1], vf[2], v[0], v[1], v[2]); if(vf[0] < 2 || (vf[0] == 2 && vf[1] < 2)){ Msg::Error("Cannot read MED file older than V2.2"); return 0; } std::vector<std::string> meshNames; for(int i = 0; i < MEDnMaa(fid); i++){ char meshName[MED_TAILLE_NOM + 1], meshDesc[MED_TAILLE_DESC + 1]; med_int spaceDim; med_maillage meshType; #if (MED_MAJOR_NUM == 3) med_int meshDim, nStep; char dtUnit[MED_SNAME_SIZE + 1]; char axisName[3 * MED_SNAME_SIZE + 1], axisUnit[3 * MED_SNAME_SIZE + 1]; med_sorting_type sortingType; med_axis_type axisType; if(MEDmeshInfo(fid, i + 1, meshName, &spaceDim, &meshDim, &meshType, meshDesc, dtUnit, &sortingType, &nStep, &axisType, axisName, axisUnit) < 0){ #else if(MEDmaaInfo(fid, i + 1, meshName, &spaceDim, &meshType, meshDesc) < 0){ #endif Msg::Error("Unable to read mesh information"); return 0; } meshNames.push_back(meshName); } if(MEDfermer(fid) < 0){ Msg::Error("Unable to close file '%s'", (char*)name.c_str()); return 0; } int ret = 1; for(unsigned int i = 0; i < meshNames.size(); i++){ // we use the filename as a kind of "partition" indicator, allowing to // complete a model part by part (used e.g. in DDM, since MED does not store // a partition index) GModel *m = findByName(meshNames[i], name); if(!m) m = new GModel(meshNames[i]); ret = m->readMED(name, i); if(!ret) return 0; } return ret; } int GModel::readMED(const std::string &name, int meshIndex) { med_idt fid = MEDouvrir((char*)name.c_str(), MED_LECTURE); if(fid < 0){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } int numMeshes = MEDnMaa(fid); if(meshIndex >= numMeshes){ Msg::Info("Could not find mesh %d in MED file", meshIndex); return 0; } checkPointMaxNumbers(); GModel::setCurrent(this); // make sure we increment max nums in this model // read mesh info char meshName[MED_TAILLE_NOM + 1], meshDesc[MED_TAILLE_DESC + 1]; med_int spaceDim, nStep = 1; med_maillage meshType; #if (MED_MAJOR_NUM == 3) med_int meshDim; char dtUnit[MED_SNAME_SIZE + 1]; char axisName[3 * MED_SNAME_SIZE + 1], axisUnit[3 * MED_SNAME_SIZE + 1]; med_sorting_type sortingType; med_axis_type axisType; if(MEDmeshInfo(fid, meshIndex + 1, meshName, &spaceDim, &meshDim, &meshType, meshDesc, dtUnit, &sortingType, &nStep, &axisType, axisName, axisUnit) < 0){ #else if(MEDmaaInfo(fid, meshIndex + 1, meshName, &spaceDim, &meshType, meshDesc) < 0){ #endif Msg::Error("Unable to read mesh information"); return 0; } // FIXME: we should support multi-step MED3 meshes (probably by // storing each mesh as a separate model, with a naming convention // e.g. meshName_step%d). This way we could also handle multi-mesh // time sequences in MED3. if(nStep > 1) Msg::Warning("Discarding %d last meshes in multi-step MED mesh", nStep - 1); setName(meshName); setFileName(name); if(meshType == MED_NON_STRUCTURE){ Msg::Info("Reading %d-D unstructured mesh <<%s>>", spaceDim, meshName); } else{ Msg::Error("Reading structured MED meshes is not supported"); return 0; } med_int vf[3]; MEDversionLire(fid, &vf[0], &vf[1], &vf[2]); // read nodes #if (MED_MAJOR_NUM == 3) med_bool changeOfCoord, geoTransform; med_int numNodes = MEDmeshnEntity(fid, meshName, MED_NO_DT, MED_NO_IT, MED_NODE, MED_NO_GEOTYPE, MED_COORDINATE, MED_NO_CMODE, &changeOfCoord, &geoTransform); #else med_int numNodes = MEDnEntMaa(fid, meshName, MED_COOR, MED_NOEUD, MED_NONE, MED_NOD); #endif if(numNodes < 0){ Msg::Error("Could not read number of MED nodes"); return 0; } if(numNodes == 0){ Msg::Error("No nodes in MED mesh"); return 0; } std::vector<MVertex*> verts(numNodes); std::vector<med_float> coord(spaceDim * numNodes); #if (MED_MAJOR_NUM == 3) if(MEDmeshNodeCoordinateRd(fid, meshName, MED_NO_DT, MED_NO_IT, MED_FULL_INTERLACE, &coord[0]) < 0){ #else std::vector<char> coordName(spaceDim * MED_TAILLE_PNOM + 1); std::vector<char> coordUnit(spaceDim * MED_TAILLE_PNOM + 1); med_repere rep; if(MEDcoordLire(fid, meshName, spaceDim, &coord[0], MED_FULL_INTERLACE, MED_ALL, 0, 0, &rep, &coordName[0], &coordUnit[0]) < 0){ #endif Msg::Error("Could not read MED node coordinates"); return 0; } std::vector<med_int> nodeTags(numNodes); #if (MED_MAJOR_NUM == 3) if(MEDmeshEntityNumberRd(fid, meshName, MED_NO_DT, MED_NO_IT, MED_NODE, MED_NO_GEOTYPE, &nodeTags[0]) < 0) #else if(MEDnumLire(fid, meshName, &nodeTags[0], numNodes, MED_NOEUD, MED_NONE) < 0) #endif nodeTags.clear(); for(int i = 0; i < numNodes; i++) verts[i] = new MVertex(coord[spaceDim * i], (spaceDim > 1) ? coord[spaceDim * i + 1] : 0., (spaceDim > 2) ? coord[spaceDim * i + 2] : 0., 0, nodeTags.empty() ? 0 : nodeTags[i]); // read elements (loop over all possible MSH element types) for(int mshType = 0; mshType < MSH_NUM_TYPE; mshType++){ med_geometrie_element type = msh2medElementType(mshType); if(type == MED_NONE) continue; #if (MED_MAJOR_NUM == 3) med_bool changeOfCoord; med_bool geoTransform; med_int numEle = MEDmeshnEntity(fid, meshName, MED_NO_DT, MED_NO_IT, MED_CELL, type, MED_CONNECTIVITY, MED_NODAL, &changeOfCoord, &geoTransform); #else med_int numEle = MEDnEntMaa(fid, meshName, MED_CONN, MED_MAILLE, type, MED_NOD); #endif if(numEle <= 0) continue; int numNodPerEle = type % 100; std::vector<med_int> conn(numEle * numNodPerEle); #if (MED_MAJOR_NUM == 3) if(MEDmeshElementConnectivityRd(fid, meshName, MED_NO_DT, MED_NO_IT, MED_CELL, type, MED_NODAL, MED_FULL_INTERLACE, &conn[0]) < 0){ #else if(MEDconnLire(fid, meshName, spaceDim, &conn[0], MED_FULL_INTERLACE, 0, MED_ALL, MED_MAILLE, type, MED_NOD) < 0){ #endif Msg::Error("Could not read MED elements"); return 0; } std::vector<med_int> fam(numEle, 0); #if (MED_MAJOR_NUM == 3) if(MEDmeshEntityFamilyNumberRd(fid, meshName, MED_NO_DT, MED_NO_IT, MED_CELL, type, &fam[0]) < 0){ #else if(MEDfamLire(fid, meshName, &fam[0], numEle, MED_MAILLE, type) < 0){ #endif Msg::Info("No family number for elements: using 0 as default family number"); } std::vector<med_int> eleTags(numEle); #if (MED_MAJOR_NUM == 3) if(MEDmeshEntityNumberRd(fid, meshName, MED_NO_DT, MED_NO_IT, MED_CELL, type, &eleTags[0]) < 0) #else if(MEDnumLire(fid, meshName, &eleTags[0], numEle, MED_MAILLE, type) < 0) #endif eleTags.clear(); std::map<int, std::vector<MElement*> > elements; MElementFactory factory; for(int j = 0; j < numEle; j++){ std::vector<MVertex*> v(numNodPerEle); for(int k = 0; k < numNodPerEle; k++) v[k] = verts[conn[numNodPerEle * j + med2mshNodeIndex(type, k)] - 1]; MElement *e = factory.create(mshType, v, eleTags.empty() ? 0 : eleTags[j]); if(e) elements[-fam[j]].push_back(e); } _storeElementsInEntities(elements); } _associateEntityWithMeshVertices(); _storeVerticesInEntities(verts); // read family info med_int numFamilies = MEDnFam(fid, meshName); if(numFamilies < 0){ Msg::Error("Could not read MED families"); return 0; } for(int i = 0; i < numFamilies; i++){ #if (MED_MAJOR_NUM == 3) med_int numAttrib = (vf[0] == 2) ? MEDnFamily23Attribute(fid, meshName, i + 1) : 0; med_int numGroups = MEDnFamilyGroup(fid, meshName, i + 1); #else med_int numAttrib = MEDnAttribut(fid, meshName, i + 1); med_int numGroups = MEDnGroupe(fid, meshName, i + 1); #endif if(numAttrib < 0 || numGroups < 0){ Msg::Error("Could not read MED groups or attributes"); return 0; } std::vector<med_int> attribId(numAttrib + 1); std::vector<med_int> attribVal(numAttrib + 1); std::vector<char> attribDes(MED_TAILLE_DESC * numAttrib + 1); std::vector<char> groupNames(MED_TAILLE_LNOM * numGroups + 1); char familyName[MED_TAILLE_NOM + 1]; med_int familyNum; #if (MED_MAJOR_NUM == 3) if(vf[0] == 2){ // MED2 file if(MEDfamily23Info(fid, meshName, i + 1, familyName, &attribId[0], &attribVal[0], &attribDes[0], &familyNum, &groupNames[0]) < 0){ Msg::Error("Could not read info for MED2 family %d", i + 1); continue; } } else{ if(MEDfamilyInfo(fid, meshName, i + 1, familyName, &familyNum, &groupNames[0]) < 0){ Msg::Error("Could not read info for MED3 family %d", i + 1); continue; } } #else if(MEDfamInfo(fid, meshName, i + 1, familyName, &familyNum, &attribId[0], &attribVal[0], &attribDes[0], &numAttrib, &groupNames[0], &numGroups) < 0){ Msg::Error("Could not read info for MED family %d", i + 1); continue; } #endif // family tags are unique (for all dimensions) GEntity *ge; if((ge = getRegionByTag(-familyNum))){} else if((ge = getFaceByTag(-familyNum))){} else if((ge = getEdgeByTag(-familyNum))){} else ge = getVertexByTag(-familyNum); if(ge){ elementaryNames[std::pair<int, int>(ge->dim(), -familyNum)] = familyName; if(numGroups > 0){ for(int j = 0; j < numGroups; j++){ char tmp[MED_TAILLE_LNOM + 1]; strncpy(tmp, &groupNames[j * MED_TAILLE_LNOM], MED_TAILLE_LNOM); tmp[MED_TAILLE_LNOM] = '\0'; // don't use same physical number across dimensions, as e.g. getdp // does not support this int pnum = setPhysicalName(tmp, ge->dim(), getMaxPhysicalNumber(-1) + 1); if(std::find(ge->physicals.begin(), ge->physicals.end(), pnum) == ge->physicals.end()) ge->physicals.push_back(pnum); } } } } // check if we need to read some post-processing data later #if (MED_MAJOR_NUM == 3) bool postpro = (MEDnField(fid) > 0) ? true : false; #else bool postpro = (MEDnChamp(fid, 0) > 0) ? true : false; #endif if(MEDfermer(fid) < 0){ Msg::Error("Unable to close file '%s'", (char*)name.c_str()); return 0; } return postpro ? 2 : 1; } template<class T> static void fillElementsMED(med_int family, std::vector<T*> &elements, std::vector<med_int> &conn, std::vector<med_int> &fam, med_geometrie_element &type) { if(elements.empty()) return; type = msh2medElementType(elements[0]->getTypeForMSH()); if(type == MED_NONE){ Msg::Warning("Unsupported element type in MED format"); return; } for(unsigned int i = 0; i < elements.size(); i++){ elements[i]->setVolumePositive(); for(int j = 0; j < elements[i]->getNumVertices(); j++) conn.push_back(elements[i]->getVertex(med2mshNodeIndex(type, j))->getIndex()); fam.push_back(family); } } static void writeElementsMED(med_idt &fid, char *meshName, std::vector<med_int> &conn, std::vector<med_int> &fam, med_geometrie_element type) { if(fam.empty()) return; #if (MED_MAJOR_NUM == 3) if(MEDmeshElementWr(fid, meshName, MED_NO_DT, MED_NO_IT, 0., MED_CELL, type, MED_NODAL, MED_FULL_INTERLACE, (med_int)fam.size(), &conn[0], MED_FALSE, 0, MED_FALSE, 0, MED_TRUE, &fam[0]) < 0) #else if(MEDelementsEcr(fid, meshName, (med_int)3, &conn[0], MED_FULL_INTERLACE, 0, MED_FAUX, 0, MED_FAUX, &fam[0], (med_int)fam.size(), MED_MAILLE, type, MED_NOD) < 0) #endif Msg::Error("Could not write MED elements"); } int GModel::writeMED(const std::string &name, bool saveAll, double scalingFactor) { med_idt fid = MEDouvrir((char*)name.c_str(), MED_CREATION); if(fid < 0){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } // write header if(MEDfichDesEcr(fid, (char*)"MED file generated by Gmsh") < 0){ Msg::Error("Unable to write MED descriptor"); return 0; } char *meshName = (char*)getName().c_str(); // Gmsh always writes 3D unstructured meshes #if (MED_MAJOR_NUM == 3) char dtUnit[MED_SNAME_SIZE + 1] = ""; char axisName[3 * MED_SNAME_SIZE + 1] = ""; char axisUnit[3 * MED_SNAME_SIZE + 1] = ""; if(MEDmeshCr(fid, meshName, 3, 3, MED_UNSTRUCTURED_MESH, "Mesh created with Gmsh", dtUnit, MED_SORT_DTIT, MED_CARTESIAN, axisName, axisUnit) < 0){ #else if(MEDmaaCr(fid, meshName, 3, MED_NON_STRUCTURE, (char*)"Mesh created with Gmsh") < 0){ #endif Msg::Error("Could not create MED mesh"); return 0; } // if there are no physicals we save all the elements if(noPhysicalGroups()) saveAll = true; // index the vertices we save in a continuous sequence (MED // connectivity is given in terms of vertex indices) indexMeshVertices(saveAll); // get a vector containing all the geometrical entities in the // model (the ordering of the entities must be the same as the one // used during the indexing of the vertices) std::vector<GEntity*> entities; getEntities(entities); std::map<GEntity*, int> families; // write the families { // always create a "0" family, with no groups or attributes #if (MED_MAJOR_NUM == 3) if(MEDfamilyCr(fid, meshName, "F_0", 0, 0, "") < 0) #else if(MEDfamCr(fid, meshName, (char*)"F_0", 0, 0, 0, 0, 0, 0, 0) < 0) #endif Msg::Error("Could not create MED family 0"); // create one family per elementary entity, with one group per // physical entity and no attributes for(unsigned int i = 0; i < entities.size(); i++){ if(saveAll || entities[i]->physicals.size()){ int num = - ((int)families.size() + 1); families[entities[i]] = num; std::ostringstream fs; fs << entities[i]->dim() << "D_" << entities[i]->tag(); std::string familyName = "F_" + fs.str(); std::string groupName; for(unsigned j = 0; j < entities[i]->physicals.size(); j++){ std::string tmp = getPhysicalName (entities[i]->dim(), entities[i]->physicals[j]); if(tmp.empty()){ // create unique name std::ostringstream gs; gs << entities[i]->dim() << "D_" << entities[i]->physicals[j]; groupName += "G_" + gs.str(); } else groupName += tmp; groupName.resize((j + 1) * MED_TAILLE_LNOM, ' '); } #if (MED_MAJOR_NUM == 3) if(MEDfamilyCr(fid, meshName, familyName.c_str(), (med_int)num, (med_int)entities[i]->physicals.size(), groupName.c_str()) < 0) #else if(MEDfamCr(fid, meshName, (char*)familyName.c_str(), (med_int)num, 0, 0, 0, 0, (char*)groupName.c_str(), (med_int)entities[i]->physicals.size()) < 0) #endif Msg::Error("Could not create MED family %d", num); } } } // write the nodes { std::vector<med_float> coord; std::vector<med_int> fam; for(unsigned int i = 0; i < entities.size(); i++){ for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++){ MVertex *v = entities[i]->mesh_vertices[j]; if(v->getIndex() >= 0){ coord.push_back(v->x() * scalingFactor); coord.push_back(v->y() * scalingFactor); coord.push_back(v->z() * scalingFactor); fam.push_back(0); // we never create node families } } } if(fam.empty()){ Msg::Error("No nodes to write in MED mesh"); return 0; } #if (MED_MAJOR_NUM == 3) if(MEDmeshNodeWr(fid, meshName, MED_NO_DT, MED_NO_IT, 0., MED_FULL_INTERLACE, (med_int)fam.size(), &coord[0], MED_FALSE, "", MED_FALSE, 0, MED_TRUE, &fam[0]) < 0) #else char coordName[3 * MED_TAILLE_PNOM + 1] = "x y z "; char coordUnit[3 * MED_TAILLE_PNOM + 1] = "unknown unknown unknown "; if(MEDnoeudsEcr(fid, meshName, (med_int)3, &coord[0], MED_FULL_INTERLACE, MED_CART, coordName, coordUnit, 0, MED_FAUX, 0, MED_FAUX, &fam[0], (med_int)fam.size()) < 0) #endif Msg::Error("Could not write nodes"); } // write the elements { { // points med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(viter it = firstVertex(); it != lastVertex(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->points, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // lines med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(eiter it = firstEdge(); it != lastEdge(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->lines, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // triangles med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(fiter it = firstFace(); it != lastFace(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->triangles, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // quads med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(fiter it = firstFace(); it != lastFace(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->quadrangles, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // tets med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(riter it = firstRegion(); it != lastRegion(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->tetrahedra, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // hexas med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(riter it = firstRegion(); it != lastRegion(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->hexahedra, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // prisms med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(riter it = firstRegion(); it != lastRegion(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->prisms, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // pyramids med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(riter it = firstRegion(); it != lastRegion(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->pyramids, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } } if(MEDfermer(fid) < 0){ Msg::Error("Unable to close file '%s'", (char*)name.c_str()); return 0; } return 1; } #else int GModel::readMED(const std::string &name) { Msg::Error("Gmsh must be compiled with MED support to read '%s'", name.c_str()); return 0; }
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; }
static void extrudeMesh(GFace *from, GRegion *to, MVertexRTree &pos) { ExtrudeParams *ep = to->meshAttributes.extrude; // interior vertices std::vector<MVertex*> mesh_vertices = from->mesh_vertices; // add all embedded vertices std::vector<MVertex*> embedded = from->getEmbeddedMeshVertices(); mesh_vertices.insert(mesh_vertices.end(), embedded.begin(), embedded.end()); // create extruded vertices for(unsigned int i = 0; i < mesh_vertices.size(); i++){ MVertex *v = mesh_vertices[i]; for(int j = 0; j < ep->mesh.NbLayer; j++) { for(int k = 0; k < ep->mesh.NbElmLayer[j]; k++) { double x = v->x(), y = v->y(), z = v->z(); ep->Extrude(j, k + 1, x, y, z); if(j != ep->mesh.NbLayer - 1 || k != ep->mesh.NbElmLayer[j] - 1){ MVertex *newv = new MVertex(x, y, z, to); to->mesh_vertices.push_back(newv); pos.insert(newv); } } } } if(ep && ep->mesh.ExtrudeMesh && ep->mesh.QuadToTri && ep->mesh.Recombine){ meshQuadToTriRegion(to, pos); return; } // create elements (note that it would be faster to access the *interior* // nodes by direct indexing, but it's just simpler to query everything by // position) for(unsigned int i = 0; i < from->triangles.size(); i++){ for(int j = 0; j < ep->mesh.NbLayer; j++) { for(int k = 0; k < ep->mesh.NbElmLayer[j]; k++) { std::vector<MVertex*> verts; if(getExtrudedVertices(from->triangles[i], ep, j, k, pos, verts) == 6) { createPriPyrTet(verts, to,from->triangles[i]); } } } } if(from->quadrangles.size() && !ep->mesh.Recombine){ Msg::Error("Cannot extrude quadrangles without Recombine"); } else{ for(unsigned int i = 0; i < from->quadrangles.size(); i++){ for(int j = 0; j < ep->mesh.NbLayer; j++) { for(int k = 0; k < ep->mesh.NbElmLayer[j]; k++) { std::vector<MVertex*> verts; if(getExtrudedVertices(from->quadrangles[i], ep, j, k, pos, verts) == 8) createHexPri(verts, to, from->quadrangles[i]); } } } } }
void highOrderTools::computeStraightSidedPositions() { _clean(); // compute straigh sided positions that are actually X,Y,Z positions // that are NOT always on curves and surfaces // points classified on model vertices shall not move ! for(GModel::viter it = _gm->firstVertex(); it != _gm->lastVertex(); ++it){ if ((*it)->points.size()){ MPoint *p = (*it)->points[0]; MVertex *v = p->getVertex(0); _straightSidedLocation [v] = SVector3((*it)->x(),(*it)->y(),(*it)->z()); _targetLocation [v] = SVector3((*it)->x(),(*it)->y(),(*it)->z()); } } // printf("coucou2\n"); // compute stright sided positions of vertices that are classified on model edges for(GModel::eiter it = _gm->firstEdge(); it != _gm->lastEdge(); ++it){ for (unsigned int i=0;i<(*it)->lines.size();i++){ MLine *l = (*it)->lines[i]; int N = l->getNumVertices()-2; SVector3 p0((*it)->lines[i]->getVertex(0)->x(), (*it)->lines[i]->getVertex(0)->y(), (*it)->lines[i]->getVertex(0)->z()); SVector3 p1((*it)->lines[i]->getVertex(1)->x(), (*it)->lines[i]->getVertex(1)->y(), (*it)->lines[i]->getVertex(1)->z()); for (int j=1;j<=N;j++){ const double xi = (double)(j)/(N+1); // printf("xi = %g\n",xi); const SVector3 straightSidedPoint = p0 *(1.-xi) + p1*xi; MVertex *v = (*it)->lines[i]->getVertex(j+1); if (_straightSidedLocation.find(v) == _straightSidedLocation.end()){ _straightSidedLocation [v] = straightSidedPoint; _targetLocation[v] = SVector3(v->x(),v->y(),v->z()); } } } } // printf("coucou3\n"); // compute stright sided positions of vertices that are classified on model faces for(GModel::fiter it = _gm->firstFace(); it != _gm->lastFace(); ++it){ for (unsigned int i=0;i<(*it)->mesh_vertices.size();i++){ MVertex *v = (*it)->mesh_vertices[i]; _targetLocation[v] = SVector3(v->x(),v->y(),v->z()); } for (unsigned int i=0;i<(*it)->triangles.size();i++){ MTriangle *t = (*it)->triangles[i]; MFace face = t->getFace(0); const nodalBasis* fs = t->getFunctionSpace(); for (int j=0;j<t->getNumVertices();j++){ if (t->getVertex(j)->onWhat() == *it){ const double t1 = fs->points(j, 0); const double t2 = fs->points(j, 1); SPoint3 pc = face.interpolate(t1, t2); _straightSidedLocation [t->getVertex(j)] = SVector3(pc.x(),pc.y(),pc.z()); } } } for (unsigned int i=0;i<(*it)->quadrangles.size();i++){ // printf("coucou quad %d\n",i); MQuadrangle *q = (*it)->quadrangles[i]; MFace face = q->getFace(0); const nodalBasis* fs = q->getFunctionSpace(); for (int j=0;j<q->getNumVertices();j++){ if (q->getVertex(j)->onWhat() == *it){ const double t1 = fs->points(j, 0); const double t2 = fs->points(j, 1); SPoint3 pc = face.interpolate(t1, t2); _straightSidedLocation [q->getVertex(j)] = SVector3(pc.x(),pc.y(),pc.z()); } } } } for(GModel::riter it = _gm->firstRegion(); it != _gm->lastRegion(); ++it){ for (unsigned int i=0;i<(*it)->mesh_vertices.size();i++){ MVertex *v = (*it)->mesh_vertices[i]; _targetLocation[v] = SVector3(v->x(),v->y(),v->z()); } for (unsigned int i=0;i<(*it)->tetrahedra.size();i++){ _dim = 3; MTetrahedron *t = (*it)->tetrahedra[i]; MTetrahedron t_1 ((*it)->tetrahedra[i]->getVertex(0), (*it)->tetrahedra[i]->getVertex(1), (*it)->tetrahedra[i]->getVertex(2), (*it)->tetrahedra[i]->getVertex(3)); const nodalBasis* fs = t->getFunctionSpace(); for (int j=0;j<t->getNumVertices();j++){ if (t->getVertex(j)->onWhat() == *it){ double t1 = fs->points(j, 0); double t2 = fs->points(j, 1); double t3 = fs->points(j, 2); SPoint3 pc; t_1.pnt(t1, t2, t3,pc); _straightSidedLocation [t->getVertex(j)] = SVector3(pc.x(),pc.y(),pc.z()); } } } for (unsigned int i=0;i<(*it)->hexahedra.size();i++){ _dim = 3; MHexahedron *h = (*it)->hexahedra[i]; MHexahedron h_1 ((*it)->hexahedra[i]->getVertex(0), (*it)->hexahedra[i]->getVertex(1), (*it)->hexahedra[i]->getVertex(2), (*it)->hexahedra[i]->getVertex(3), (*it)->hexahedra[i]->getVertex(4), (*it)->hexahedra[i]->getVertex(5), (*it)->hexahedra[i]->getVertex(6), (*it)->hexahedra[i]->getVertex(7)); const nodalBasis* fs = h->getFunctionSpace(); for (int j=0;j<h->getNumVertices();j++){ if (h->getVertex(j)->onWhat() == *it){ double t1 = fs->points(j, 0); double t2 = fs->points(j, 1); double t3 = fs->points(j, 2); SPoint3 pc; h_1.pnt(t1, t2, t3,pc); _straightSidedLocation [h->getVertex(j)] = SVector3(pc.x(),pc.y(),pc.z()); } } } } Msg::Info("highOrderTools has been set up : %d nodes are considered", _straightSidedLocation.size()); }
//------------------------------------------------ void RglCube(MVertex &c, MVertex &v1, MVertex &v2, float depth, int detail, GLuint *texArray) { float A0[3] = { c.x(), c.y(), c.z() }; float B0[3] = { A0[0] + v2.x(), A0[1] + v2.y(), A0[2] + v2.z() }; float C0[3] = { B0[0] + v1.x(), B0[1] + v1.y(), B0[2] + v1.z() }; float D0[3] = { A0[0] + v1.x(), A0[1] + v1.y(), A0[2] + v1.z() }; float p0[2][2][3]; // Get corners A, B, C and D p0[0][0][0] = C0[0]; p0[0][0][1] = C0[1]; p0[0][0][2] = -C0[2]; p0[0][1][0] = B0[0]; p0[0][1][1] = B0[1]; p0[0][1][2] = -B0[2]; p0[1][1][0] = A0[0]; p0[1][1][1] = A0[1]; p0[1][1][2] = -A0[2]; p0[1][0][0] = D0[0]; p0[1][0][1] = D0[1]; p0[1][0][2] = -D0[2]; GLuint curTex = 0; if(texArray) { curTex = texArray[0]; glBindTexture(GL_TEXTURE_2D, curTex); } RglBilinearPatch(p0, detail); //-- if plane has depth, draw it... if (depth != 0.0f) { MVertex v1(D0[0], D0[1], D0[2]); MVertex v2(A0[0], A0[1], A0[2]); MVertex v3(B0[0], B0[1], B0[2]); MVertex normal; normal.CreateNormal(v1, v2, v3); normal.setX(normal.x()*depth); normal.setY(normal.y()*depth); normal.setZ(normal.z()*depth); float A1[3]; float B1[3]; float C1[3]; float D1[3]; A1[0] = A0[0]-normal.x(); A1[1] = A0[1]-normal.y(); A1[2] = A0[2]-normal.z(); B1[0] = B0[0]-normal.x(); B1[1] = B0[1]-normal.y(); B1[2] = B0[2]-normal.z(); C1[0] = C0[0]-normal.x(); C1[1] = C0[1]-normal.y(); C1[2] = C0[2]-normal.z(); D1[0] = D0[0]-normal.x(); D1[1] = D0[1]-normal.y(); D1[2] = D0[2]-normal.z(); p0[0][0][0] = C1[0]; p0[0][0][1] = C1[1]; p0[0][0][2] = -C1[2]; p0[0][1][0] = D1[0]; p0[0][1][1] = D1[1]; p0[0][1][2] = -D1[2]; p0[1][1][0] = A1[0]; p0[1][1][1] = A1[1]; p0[1][1][2] = -A1[2]; p0[1][0][0] = B1[0]; p0[1][0][1] = B1[1]; p0[1][0][2] = -B1[2]; float p1[2][2][3]; float p2[2][2][3]; float p3[2][2][3]; float p4[2][2][3]; p1[0][0][0] = B0[0]; p1[0][0][1] = B0[1]; p1[0][0][2] = -B0[2]; p1[0][1][0] = B1[0]; p1[0][1][1] = B1[1]; p1[0][1][2] = -B1[2]; p1[1][1][0] = A1[0]; p1[1][1][1] = A1[1]; p1[1][1][2] = -A1[2]; p1[1][0][0] = A0[0]; p1[1][0][1] = A0[1]; p1[1][0][2] = -A0[2]; p2[0][0][0] = C0[0]; p2[0][0][1] = C0[1]; p2[0][0][2] = -C0[2]; p2[0][1][0] = C1[0]; p2[0][1][1] = C1[1]; p2[0][1][2] = -C1[2]; p2[1][1][0] = B1[0]; p2[1][1][1] = B1[1]; p2[1][1][2] = -B1[2]; p2[1][0][0] = B0[0]; p2[1][0][1] = B0[1]; p2[1][0][2] = -B0[2]; p3[0][0][0] = D0[0]; p3[0][0][1] = D0[1]; p3[0][0][2] = -D0[2]; p3[0][1][0] = D1[0]; p3[0][1][1] = D1[1]; p3[0][1][2] = -D1[2]; p3[1][1][0] = C1[0]; p3[1][1][1] = C1[1]; p3[1][1][2] = -C1[2]; p3[1][0][0] = C0[0]; p3[1][0][1] = C0[1]; p3[1][0][2] = -C0[2]; p4[0][0][0] = A0[0]; p4[0][0][1] = A0[1]; p4[0][0][2] = -A0[2]; p4[0][1][0] = A1[0]; p4[0][1][1] = A1[1]; p4[0][1][2] = -A1[2]; p4[1][1][0] = D1[0]; p4[1][1][1] = D1[1]; p4[1][1][2] = -D1[2]; p4[1][0][0] = D0[0]; p4[1][0][1] = D0[1]; p4[1][0][2] = -D0[2]; if(texArray) { //if(texArray[1] != curTex) { curTex = texArray[1]; glBindTexture(GL_TEXTURE_2D, curTex); } RglBilinearPatch(p0, detail); //if(texArray[2] != curTex) { curTex = texArray[2]; glBindTexture(GL_TEXTURE_2D, curTex); } RglBilinearPatch(p1, detail); //if(texArray[3] != curTex) { curTex = texArray[3]; glBindTexture(GL_TEXTURE_2D, curTex); } RglBilinearPatch(p2, detail); //if(texArray[4] != curTex) { curTex = texArray[4]; glBindTexture(GL_TEXTURE_2D, curTex); } RglBilinearPatch(p3, detail); //if(texArray[5] != curTex) { curTex = texArray[5]; glBindTexture(GL_TEXTURE_2D, curTex); } RglBilinearPatch(p4, detail); } else { RglBilinearPatch(p0, detail); RglBilinearPatch(p1, detail); RglBilinearPatch(p2, detail); RglBilinearPatch(p3, detail); RglBilinearPatch(p4, detail); } } }
int GModel::writeP3D(const std::string &name, bool saveAll, double scalingFactor) { FILE *fp = Fopen(name.c_str(), "w"); if(!fp) { Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } if(noPhysicalGroups()) saveAll = true; std::vector<GFace *> faces; for(fiter it = firstFace(); it != lastFace(); ++it) if((*it)->transfinite_vertices.size() && (*it)->transfinite_vertices[0].size() && ((*it)->physicals.size() || saveAll)) faces.push_back(*it); std::vector<GRegion *> regions; for(riter it = firstRegion(); it != lastRegion(); ++it) if((*it)->transfinite_vertices.size() && (*it)->transfinite_vertices[0].size() && (*it)->transfinite_vertices[0][0].size() && ((*it)->physicals.size() || saveAll)) regions.push_back(*it); if(faces.empty() && regions.empty()) { Msg::Warning("No structured grids to save"); fclose(fp); return 0; } fprintf(fp, "%d\n", (int)(faces.size() + regions.size())); for(std::size_t i = 0; i < faces.size(); i++) fprintf(fp, "%d %d 1\n", (int)faces[i]->transfinite_vertices.size(), (int)faces[i]->transfinite_vertices[0].size()); for(std::size_t i = 0; i < regions.size(); i++) fprintf(fp, "%d %d %d\n", (int)regions[i]->transfinite_vertices.size(), (int)regions[i]->transfinite_vertices[0].size(), (int)regions[i]->transfinite_vertices[0][0].size()); for(std::size_t i = 0; i < faces.size(); i++) { GFace *gf = faces[i]; for(int coord = 0; coord < 3; coord++) { for(std::size_t k = 0; k < gf->transfinite_vertices[0].size(); k++) { for(std::size_t j = 0; j < gf->transfinite_vertices.size(); j++) { MVertex *v = gf->transfinite_vertices[j][k]; double d = (coord == 0) ? v->x() : (coord == 1) ? v->y() : v->z(); fprintf(fp, "%.16g ", d * scalingFactor); } fprintf(fp, "\n"); } } } for(std::size_t i = 0; i < regions.size(); i++) { GRegion *gr = regions[i]; for(int coord = 0; coord < 3; coord++) { for(std::size_t l = 0; l < gr->transfinite_vertices[0][0].size(); l++) { for(std::size_t k = 0; k < gr->transfinite_vertices[0].size(); k++) { for(std::size_t j = 0; j < gr->transfinite_vertices.size(); j++) { MVertex *v = gr->transfinite_vertices[j][k][l]; double d = (coord == 0) ? v->x() : (coord == 1) ? v->y() : v->z(); fprintf(fp, "%.16g ", d * scalingFactor); } fprintf(fp, "\n"); } } } } fclose(fp); return 1; }
// 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; }