Metric Filler::get_metric(double x,double y,double z,GEntity* ge){ Metric m; SMetric3 temp; SVector3 v1,v2,v3; Field* field; FieldManager* manager; v1 = SVector3(1.0,0.0,0.0); v2 = SVector3(0.0,1.0,0.0); v3 = SVector3(0.0,0.0,1.0); manager = ge->model()->getFields(); if(manager->getBackgroundField()>0){ field = manager->get(manager->getBackgroundField()); if(field){ (*field)(x,y,z,temp,ge); } } m.set_m11(v1.x()); m.set_m21(v1.y()); m.set_m31(v1.z()); m.set_m12(v2.x()); m.set_m22(v2.y()); m.set_m32(v2.z()); m.set_m13(v3.x()); m.set_m23(v3.y()); m.set_m33(v3.z()); return m; }
double Filler::get_size(double x,double y,double z,GEntity* ge){ double h; Field* field; FieldManager* manager; h = 1.0; manager = ge->model()->getFields(); if(manager->getBackgroundField()>0){ field = manager->get(manager->getBackgroundField()); if(field){ h = (*field)(x,y,z,ge); } } return h; }
// anisotropic version of the background field SMetric3 BGM_MeshMetric(GEntity *ge, double U, double V, double X, double Y, double Z) { // Metrics based on element size // Element size = min. between default lc and lc from point (if applicable), // constrained by lcMin and lcMax double lc = CTX::instance()->lc; if(CTX::instance()->mesh.lcFromPoints && ge->dim() < 2) lc = std::min(lc, LC_MVertex_PNTS(ge, U, V)); lc = std::min(lc, ge->getMeshSize()); lc = std::max(lc, CTX::instance()->mesh.lcMin); lc = std::min(lc, CTX::instance()->mesh.lcMax); if(lc <= 0.){ Msg::Error("Wrong mesh element size lc = %g (lcmin = %g, lcmax = %g)", lc, CTX::instance()->mesh.lcMin, CTX::instance()->mesh.lcMax); lc = CTX::instance()->lc; } SMetric3 m0(1./(lc*lc)); // Intersect with metrics from fields if applicable FieldManager *fields = ge->model()->getFields(); SMetric3 m1 = m0; if(fields->getBackgroundField() > 0){ Field *f = fields->get(fields->getBackgroundField()); if(f) { SMetric3 l4; if (!f->isotropic()) (*f)(X, Y, Z, l4, ge); else { const double L = (*f)(X, Y, Z, ge); l4 = SMetric3(1/(L*L)); } m1 = intersection(l4, m0); } } // Intersect with metrics from curvature if applicable SMetric3 m = (CTX::instance()->mesh.lcFromCurvature && ge->dim() < 3) ? intersection(m1, LC_MVertex_CURV_ANISO(ge, U, V)) : m1; return m; }
// This is the only function that is used by the meshers double BGM_MeshSize(GEntity *ge, double U, double V, double X, double Y, double Z) { // default lc (mesh size == size of the model) double l1 = CTX::instance()->lc; // lc from points double l2 = MAX_LC; if(CTX::instance()->mesh.lcFromPoints && ge->dim() < 2) l2 = LC_MVertex_PNTS(ge, U, V); // lc from curvature double l3 = MAX_LC; if(CTX::instance()->mesh.lcFromCurvature && ge->dim() < 3) l3 = LC_MVertex_CURV(ge, U, V); // lc from fields double l4 = MAX_LC; FieldManager *fields = ge->model()->getFields(); if(fields->getBackgroundField() > 0){ Field *f = fields->get(fields->getBackgroundField()); if(f) l4 = (*f)(X, Y, Z, ge); } // global lc from entity double l5 = ge->getMeshSize(); // take the minimum, then constrain by lcMin and lcMax double lc = std::min(std::min(std::min(std::min(l1, l2), l3), l4), l5); lc = std::max(lc, CTX::instance()->mesh.lcMin); lc = std::min(lc, CTX::instance()->mesh.lcMax); if(lc <= 0.){ Msg::Error("Wrong mesh element size lc = %g (lcmin = %g, lcmax = %g)", lc, CTX::instance()->mesh.lcMin, CTX::instance()->mesh.lcMax); lc = l1; } return lc * CTX::instance()->mesh.lcFactor; }
static double F_Lc_aniso(GEdge *ge, double t) { #if defined(HAVE_ANN) FieldManager *fields = ge->model()->getFields(); BoundaryLayerField *blf = 0; Field *bl_field = fields->get(fields->getBoundaryLayerField()); blf = dynamic_cast<BoundaryLayerField*> (bl_field); #else bool blf = false; #endif GPoint p = ge->point(t); SMetric3 lc_here; Range<double> bounds = ge->parBounds(0); double t_begin = bounds.low(); double t_end = bounds.high(); if(t == t_begin) lc_here = BGM_MeshMetric(ge->getBeginVertex(), t, 0, p.x(), p.y(), p.z()); else if(t == t_end) lc_here = BGM_MeshMetric(ge->getEndVertex(), t, 0, p.x(), p.y(), p.z()); else lc_here = BGM_MeshMetric(ge, t, 0, p.x(), p.y(), p.z()); #if defined(HAVE_ANN) if (blf && !blf->isEdgeBL(ge->tag())){ SMetric3 lc_bgm; blf->computeFor1dMesh ( p.x(), p.y(), p.z() , lc_bgm ); lc_here = intersection_conserveM1 (lc_here, lc_bgm ); } #endif SVector3 der = ge->firstDer(t); double lSquared = dot(der, lc_here, der); return sqrt(lSquared); }
void meshGEdge::operator() (GEdge *ge) { #if defined(HAVE_ANN) FieldManager *fields = ge->model()->getFields(); BoundaryLayerField *blf = 0; Field *bl_field = fields->get(fields->getBoundaryLayerField()); blf = dynamic_cast<BoundaryLayerField*> (bl_field); #else bool blf = false; #endif ge->model()->setCurrentMeshEntity(ge); if(ge->geomType() == GEntity::DiscreteCurve) return; if(ge->geomType() == GEntity::BoundaryLayerCurve) return; if(ge->meshAttributes.method == MESH_NONE) return; if(CTX::instance()->mesh.meshOnlyVisible && !ge->getVisibility()) return; // look if we are doing the STL triangulation std::vector<MVertex*> &mesh_vertices = ge->mesh_vertices ; std::vector<MLine*> &lines = ge->lines ; deMeshGEdge dem; dem(ge); if(MeshExtrudedCurve(ge)) return; if (ge->meshMaster() != ge){ GEdge *gef = dynamic_cast<GEdge*> (ge->meshMaster()); if (gef->meshStatistics.status == GEdge::PENDING) return; Msg::Info("Meshing curve %d (%s) as a copy of %d", ge->tag(), ge->getTypeString().c_str(), ge->meshMaster()->tag()); copyMesh(gef, ge, ge->masterOrientation); ge->meshStatistics.status = GEdge::DONE; return; } Msg::Info("Meshing curve %d (%s)", ge->tag(), ge->getTypeString().c_str()); // compute bounds Range<double> bounds = ge->parBounds(0); double t_begin = bounds.low(); double t_end = bounds.high(); // first compute the length of the curve by integrating one double length; std::vector<IntPoint> Points; if(ge->geomType() == GEntity::Line && ge->getBeginVertex() == ge->getEndVertex() && //do not consider closed lines as degenerated (ge->position(0.5) - ge->getBeginVertex()->xyz()).norm() < CTX::instance()->geom.tolerance) length = 0.; // special case t avoid infinite loop in integration else length = Integration(ge, t_begin, t_end, F_One, Points, 1.e-8 * CTX::instance()->lc); ge->setLength(length); Points.clear(); if(length < CTX::instance()->mesh.toleranceEdgeLength){ ge->setTooSmall(true); } // Integrate detJ/lc du double a; int N; if(length == 0. && CTX::instance()->mesh.toleranceEdgeLength == 0.){ Msg::Warning("Curve %d has a zero length", ge->tag()); a = 0.; N = 1; } else if(ge->degenerate(0)){ a = 0.; N = 1; } else if(ge->meshAttributes.method == MESH_TRANSFINITE){ a = Integration(ge, t_begin, t_end, F_Transfinite, Points, CTX::instance()->mesh.lcIntegrationPrecision); N = ge->meshAttributes.nbPointsTransfinite; if(CTX::instance()->mesh.flexibleTransfinite && CTX::instance()->mesh.lcFactor) N /= CTX::instance()->mesh.lcFactor; } else{ if (CTX::instance()->mesh.algo2d == ALGO_2D_BAMG || blf){ a = Integration(ge, t_begin, t_end, F_Lc_aniso, Points, CTX::instance()->mesh.lcIntegrationPrecision); } else{ a = Integration(ge, t_begin, t_end, F_Lc, Points, CTX::instance()->mesh.lcIntegrationPrecision); } // we should maybe provide an option to disable the smoothing for (unsigned int i = 0; i < Points.size(); i++){ IntPoint &pt = Points[i]; SVector3 der = ge->firstDer(pt.t); pt.xp = der.norm(); } a = smoothPrimitive(ge, sqrt(CTX::instance()->mesh.smoothRatio), Points); N = std::max(ge->minimumMeshSegments() + 1, (int)(a + 1.99)); } // force odd number of points if blossom is used for recombination if((ge->meshAttributes.method != MESH_TRANSFINITE || CTX::instance()->mesh.flexibleTransfinite) && CTX::instance()->mesh.algoRecombine != 0){ if(CTX::instance()->mesh.recombineAll){ if (N % 2 == 0) N++; if (CTX::instance()->mesh.algoRecombine == 2) N = increaseN(N); } else{ std::list<GFace*> faces = ge->faces(); for(std::list<GFace*>::iterator it = faces.begin(); it != faces.end(); it++){ if((*it)->meshAttributes.recombine){ if (N % 2 == 0) N ++; if (CTX::instance()->mesh.algoRecombine == 2) N = increaseN(N); break; } } } } // printFandPrimitive(ge->tag(),Points); // if the curve is periodic and if the begin vertex is identical to // the end vertex and if this vertex has only one model curve // adjacent to it, then the vertex is not connecting any other // curve. So, the mesh vertex and its associated geom vertex are not // necessary at the same location GPoint beg_p, end_p; if(ge->getBeginVertex() == ge->getEndVertex() && ge->getBeginVertex()->edges().size() == 1){ end_p = beg_p = ge->point(t_begin); Msg::Debug("Meshing periodic closed curve"); } else{ MVertex *v0 = ge->getBeginVertex()->mesh_vertices[0]; MVertex *v1 = ge->getEndVertex()->mesh_vertices[0]; beg_p = GPoint(v0->x(), v0->y(), v0->z()); end_p = GPoint(v1->x(), v1->y(), v1->z()); } // do not consider the first and the last vertex (those are not // classified on this mesh edge) if(N > 1){ const double b = a / (double)(N - 1); int count = 1, NUMP = 1; IntPoint P1, P2; mesh_vertices.resize(N - 2); while(NUMP < N - 1) { P1 = Points[count - 1]; P2 = Points[count]; const double d = (double)NUMP * b; if((fabs(P2.p) >= fabs(d)) && (fabs(P1.p) < fabs(d))) { double dt = P2.t - P1.t; double dlc = P2.lc - P1.lc; double dp = P2.p - P1.p; double t = P1.t + dt / dp * (d - P1.p); SVector3 der = ge->firstDer(t); const double d = norm(der); double lc = d/(P1.lc + dlc / dp * (d - P1.p)); GPoint V = ge->point(t); mesh_vertices[NUMP - 1] = new MEdgeVertex(V.x(), V.y(), V.z(), ge, t, lc); NUMP++; } else { count++; } } mesh_vertices.resize(NUMP - 1); } for(unsigned int i = 0; i < mesh_vertices.size() + 1; i++){ MVertex *v0 = (i == 0) ? ge->getBeginVertex()->mesh_vertices[0] : mesh_vertices[i - 1]; MVertex *v1 = (i == mesh_vertices.size()) ? ge->getEndVertex()->mesh_vertices[0] : mesh_vertices[i]; lines.push_back(new MLine(v0, v1)); } if(ge->getBeginVertex() == ge->getEndVertex() && ge->getBeginVertex()->edges().size() == 1){ MVertex *v0 = ge->getBeginVertex()->mesh_vertices[0]; v0->x() = beg_p.x(); v0->y() = beg_p.y(); v0->z() = beg_p.z(); } ge->meshStatistics.status = GEdge::DONE; }
bool frameFieldBackgroundMesh2D::compute_RK_infos(double u,double v, double x, double y, double z, RK_form &infos) { // check if point is in domain if (!inDomain(u,v)) return false; // get stored angle double angle_current = angle(u,v); // compute t1,t2: cross field directions // get the unit normal at that point GFace *face = dynamic_cast<GFace*>(gf); if(!face) { Msg::Error("Entity is not a face in background mesh"); return false; } Pair<SVector3, SVector3> der = face->firstDer(SPoint2(u,v)); SVector3 s1 = der.first(); SVector3 s2 = der.second(); SVector3 n = crossprod(s1,s2); n.normalize(); SVector3 basis_u = s1; basis_u.normalize(); SVector3 basis_v = crossprod(n,basis_u); // normalize vector t1 that is tangent to gf at uv SVector3 t1 = basis_u * cos(angle_current) + basis_v * sin(angle_current) ; t1.normalize(); // compute the second direction t2 and normalize (t1,t2,n) is the tangent frame SVector3 t2 = crossprod(n,t1); t2.normalize(); // get metric double L = size(u,v); infos.metricField = SMetric3(1./(L*L)); FieldManager *fields = gf->model()->getFields(); if(fields->getBackgroundField() > 0) { Field *f = fields->get(fields->getBackgroundField()); if (!f->isotropic()) { (*f)(x,y,z, infos.metricField,gf); } else { L = (*f)(x,y,z,gf); infos.metricField = SMetric3(1./(L*L)); } } double M = dot(s1,s1); double N = dot(s2,s2); double E = dot(s1,s2); // compute the first fundamental form i.e. the metric tensor at the point // M_{ij} = s_i \cdot s_j double metric[2][2] = {{M,E},{E,N}}; // get sizes double size_1 = sqrt(1. / dot(t1,infos.metricField,t1)); double size_2 = sqrt(1. / dot(t2,infos.metricField,t2)); // compute covariant coordinates of t1 and t2 - cross field directions in parametric domain double covar1[2],covar2[2]; // t1 = a s1 + b s2 --> // t1 . s1 = a M + b E // t1 . s2 = a E + b N --> solve the 2 x 2 system // and get covariant coordinates a and b double rhs1[2] = {dot(t1,s1),dot(t1,s2)}; bool singular = false; if (!sys2x2(metric,rhs1,covar1)) { Msg::Info("Argh surface %d %g %g %g -- %g %g %g -- %g %g",gf->tag(),s1.x(),s1.y(),s1.z(),s2.x(),s2.y(),s2.z(),size_1,size_2); covar1[1] = 1.0; covar1[0] = 0.0; singular = true; } double rhs2[2] = {dot(t2,s1),dot(t2,s2)}; if (!sys2x2(metric,rhs2,covar2)) { Msg::Info("Argh surface %d %g %g %g -- %g %g %g",gf->tag(),s1.x(),s1.y(),s1.z(),s2.x(),s2.y(),s2.z()); covar2[0] = 1.0; covar2[1] = 0.0; singular = true; } // transform the sizes with respect to the metric // consider a vector v of size 1 in the parameter plane // its length is sqrt (v^T M v) --> if I want a real size // of size1 in direction v, it should be sqrt(v^T M v) * size1 double l1 = sqrt(covar1[0]*covar1[0]+covar1[1]*covar1[1]); double l2 = sqrt(covar2[0]*covar2[0]+covar2[1]*covar2[1]); covar1[0] /= l1; covar1[1] /= l1; covar2[0] /= l2; covar2[1] /= l2; double size_param_1 = size_1 / sqrt ( M*covar1[0]*covar1[0]+ 2*E*covar1[1]*covar1[0]+ N*covar1[1]*covar1[1]); double size_param_2 = size_2 / sqrt ( M*covar2[0]*covar2[0]+ 2*E*covar2[1]*covar2[0]+ N*covar2[1]*covar2[1]); if (singular) { size_param_1 = size_param_2 = std::min (size_param_1,size_param_2); } // filling form... infos.t1 = t1; infos.h.first = size_1; infos.h.second = size_2; infos.paramh.first = size_param_1; infos.paramh.second = size_param_2; infos.paramt1 = SPoint2(covar1[0],covar1[1]); infos.paramt2 = SPoint2(covar2[0],covar2[1]); infos.angle = angle_current; infos.localsize = L; infos.normal = n; return true; }
bool gmshFace::buildSTLTriangulation(bool force) { return false; if(va_geom_triangles){ if(force) delete va_geom_triangles; else return true; } stl_vertices.clear(); stl_triangles.clear(); #if defined(HAVE_MESH) if (!triangles.size()){ contextMeshOptions _temp = CTX::instance()->mesh; FieldManager *fields = model()->getFields(); int BGM = fields->getBackgroundField(); fields->setBackgroundField(0); CTX::instance()->mesh.lcFromPoints = 0; CTX::instance()->mesh.lcFromCurvature = 1; CTX::instance()->mesh.lcExtendFromBoundary = 0; CTX::instance()->mesh.scalingFactor = 1; CTX::instance()->mesh.lcFactor = 1; CTX::instance()->mesh.order = 1; CTX::instance()->mesh.lcIntegrationPrecision = 1.e-3; // CTX::instance()->mesh.Algorithm = 5; model()->mesh(2); CTX::instance()->mesh = _temp; fields->setBackgroundField(fields->get(BGM)); } #endif std::map<MVertex*,int> _v; int COUNT =0; for (unsigned int j = 0; j < triangles.size(); j++){ for (int i = 0; i < 3; i++){ std::map<MVertex*,int>::iterator it = _v.find(triangles[j]->getVertex(j)); if (it != _v.end()){ stl_triangles.push_back(COUNT); _v[triangles[j]->getVertex(j)] = COUNT++; } else stl_triangles.push_back(it->second); } } std::map<MVertex*,int>::iterator itv = _v.begin(); for ( ; itv != _v.end() ; ++itv){ MVertex *v = itv->first; SPoint2 param; reparamMeshVertexOnFace(v, this, param); stl_vertices.push_back(param); } va_geom_triangles = new VertexArray(3, stl_triangles.size() / 3); unsigned int c = CTX::instance()->color.geom.surface; unsigned int col[4] = {c, c, c, c}; for (unsigned int i = 0; i < stl_triangles.size(); i += 3){ SPoint2 &p1(stl_vertices[stl_triangles[i]]); SPoint2 &p2(stl_vertices[stl_triangles[i + 1]]); SPoint2 &p3(stl_vertices[stl_triangles[i + 2]]); GPoint gp1 = GFace::point(p1); GPoint gp2 = GFace::point(p2); GPoint gp3 = GFace::point(p3); double x[3] = {gp1.x(), gp2.x(), gp3.x()}; double y[3] = {gp1.y(), gp2.y(), gp3.y()}; double z[3] = {gp1.z(), gp2.z(), gp3.z()}; SVector3 n[3] = {normal(p1), normal(p2), normal(p3)}; va_geom_triangles->add(x, y, z, n, col); } va_geom_triangles->finalize(); return true; }