diff --git a/Geo/GModelIO_Fourier.cpp b/Geo/GModelIO_Fourier.cpp index 7ff9057d92f9f8aac541f5888cb78c25e04acf14..733785858d610e3fdc7408b5fa49200ed68e61db 100644 --- a/Geo/GModelIO_Fourier.cpp +++ b/Geo/GModelIO_Fourier.cpp @@ -85,10 +85,27 @@ public: void operator() (GFace *gf) { int M = (int)(30. / CTX.mesh.lc_factor), N = (int)(30. / CTX.mesh.lc_factor); + + //if(gf->tag() == 2){ + //M = 9; + //N = 15; + //} + for(int i = 0; i < M; i++){ for(int j = 0; j < N; j++){ double u = i/(double)(M - 1); double v = j/(double)(N - 1); + + //if(gf->tag() == 2){ + // hack for sttr report 2 (ship model, top right patch) + // XYZ_values_ship_Top(u,v=0) = + // XYZ_values_ship_Med(u*matching_const1_+matching_const2_,v=1) + // where 0=<u=<1, + // matching_const1_=0.523540136032613, + // matching_const2_=0.475747890863610. + //u = u * 0.5268 + 0.475; + //} + GPoint p = gf->point(u, v); double pou=1; //FM->GetPou(gf->tag(), u, v, pou); @@ -109,6 +126,21 @@ public: } }; +class meshGmsh{ +public: + void operator() (GFace *gf) + { + fourierFace *ff = dynamic_cast<fourierFace*>(gf); + if(!ff) { + Msg(GERROR, "face %d is not Fourier", gf->tag()); + return; + } + ff->meshBoundary(); + meshGFace mesh; + mesh(ff); + } +}; + class computePartitionOfUnity{ public: void operator() (GFace *gf) @@ -586,6 +618,87 @@ fourierFace::~fourierFace() } } +void fourierFace::meshBoundary() +{ + _discrete = 0; + + int nu=0, nv=0; + FM->GetNum(tag(), nu, nv); + + std::vector<double> u, v; + FM->GetBoundary_Points(tag(), u, v); + + if(2*nu+2*nv != u.size()){ + Msg(INFO, "Special patch from youngae: %d", tag()); + GPoint p0 = point(u[0], v[0]); + GPoint p1 = point(u[1], v[1]); + MVertex *v0 = new MFaceVertex(p0.x(), p0.y(), p0.z(), this, u[0], v[0]); + MVertex *v1 = new MFaceVertex(p1.x(), p1.y(), p1.z(), this, u[1], v[1]); + _v[0] = new fourierVertex(model(), v0); + _v[1] = new fourierVertex(model(), v1); + _e[0] = new fourierEdge(model(), 1, _v[0], _v[1]); + _e[0]->addFace(this); + _e[1] = new fourierEdge(model(), 2, _v[1], _v[0]); + _e[1]->addFace(this); + for(unsigned int i = 2; i < u.size() - 1; i++){ + if(u[i] != u[i-1] || v[i] != v[i-1]){ + GPoint p = point(u[i], v[i]); + MVertex *vv = new MFaceVertex(p.x(), p.y(), p.z(), this, u[i], v[i]); + _e[1]->mesh_vertices.push_back(vv); + } + } + l_edges.push_back(_e[0]); l_dirs.push_back(1); + l_edges.push_back(_e[1]); l_dirs.push_back(1); + return; + } + + int corners[4] = {0, nu, nu + nv, 2 * nu + nv}; + for(int i = 0; i < 4; i++){ + double uu = u[corners[i]], vv = v[corners[i]]; + GPoint p = point(uu, vv); + MVertex *newv = new MFaceVertex(p.x(), p.y(), p.z(), this, uu, vv); + _v[i] = new fourierVertex(model(), newv); + } + + meshAttributes.Method = TRANSFINI; + meshAttributes.recombine = 1; + meshAttributes.transfiniteArrangement = 1; + meshAttributes.corners.clear(); + for(int i = 0; i < 4; i++) + meshAttributes.corners.push_back(_v[i]); + + _e[0] = new fourierEdge(model(), 1, _v[0], _v[1]); + _e[0]->addFace(this); + _e[1] = new fourierEdge(model(), 2, _v[1], _v[2]); + _e[1]->addFace(this); + _e[2] = new fourierEdge(model(), 3, _v[2], _v[3]); + _e[2]->addFace(this); + _e[3] = new fourierEdge(model(), 4, _v[3], _v[0]); + _e[3]->addFace(this); + + for(unsigned int i = corners[0] + 1; i < corners[1] - 1; i++){ + GPoint p = point(u[i], v[i]); + _e[0]->mesh_vertices.push_back(new MFaceVertex(p.x(), p.y(), p.z(), this, u[i], v[i])); + } + for(unsigned int i = corners[1] + 1; i < corners[2] - 1; i++){ + GPoint p = point(u[i], v[i]); + _e[1]->mesh_vertices.push_back(new MFaceVertex(p.x(), p.y(), p.z(), this, u[i], v[i])); + } + for(unsigned int i = corners[2] + 1; i < corners[3] - 1; i++){ + GPoint p = point(u[i], v[i]); + _e[2]->mesh_vertices.push_back(new MFaceVertex(p.x(), p.y(), p.z(), this, u[i], v[i])); + } + for(unsigned int i = corners[3] + 1; i < u.size() - 1; i++){ + GPoint p = point(u[i], v[i]); + _e[3]->mesh_vertices.push_back(new MFaceVertex(p.x(), p.y(), p.z(), this, u[i], v[i])); + } + + l_edges.push_back(_e[0]); l_dirs.push_back(1); + l_edges.push_back(_e[1]); l_dirs.push_back(1); + l_edges.push_back(_e[2]); l_dirs.push_back(1); + l_edges.push_back(_e[3]); l_dirs.push_back(1); +} + Range<double> fourierFace::parBounds(int i) const { double min, max; @@ -656,8 +769,12 @@ int GModel::readFourier(const std::string &name) add(new fourierFace(this, i)); // mesh each face with quads - std::for_each(firstFace(), lastFace(), meshCartesian()); + //std::for_each(firstFace(), lastFace(), meshCartesian()); + //return 1; + // mesh each face using the standard gmsh algorithms + setMeshSize(0.1); + std::for_each(firstFace(), lastFace(), meshGmsh()); return 1; // compute partition of unity diff --git a/Geo/Makefile b/Geo/Makefile index e304a138a0c72aee1a81e7b6bd96afeb924828c3..a4b8193d30bd45d948fcb3a29a64bbf434eada40 100644 --- a/Geo/Makefile +++ b/Geo/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.122 2006-12-20 15:50:57 remacle Exp $ +# $Id: Makefile,v 1.123 2006-12-21 17:10:15 geuzaine Exp $ # # Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle # @@ -104,12 +104,18 @@ GRegion.o: GRegion.cpp GModel.h GVertex.h GEntity.h Range.h SPoint3.h \ ../Numeric/Numeric.h ../Common/Context.h ../DataStr/List.h \ ExtrudeParams.h GFace.h GEdgeLoop.h Pair.h GRegion.h \ ../Common/SmoothNormals.h -gmshEdge.o: gmshEdge.cpp gmshEdge.h Geo.h ../Common/GmshDefines.h \ - ../DataStr/List.h ../DataStr/Tree.h ../DataStr/avl.h ExtrudeParams.h \ - GEdge.h GEntity.h Range.h SPoint3.h SBoundingBox3d.h GVertex.h \ - MVertex.h GPoint.h SPoint2.h SVector3.h MElement.h MEdge.h \ - ../Common/Hash.h MFace.h ../Numeric/Numeric.h ../Common/Context.h \ - gmshVertex.h GeoInterpolation.h +gmshVertex.o: gmshVertex.cpp GFace.h GPoint.h GEntity.h Range.h SPoint3.h \ + SBoundingBox3d.h ../Common/GmshDefines.h GEdgeLoop.h GEdge.h GVertex.h \ + MVertex.h SPoint2.h SVector3.h MElement.h MEdge.h ../Common/Hash.h \ + MFace.h ../Numeric/Numeric.h ../Common/Context.h ../DataStr/List.h \ + ExtrudeParams.h Pair.h gmshVertex.h Geo.h ../DataStr/Tree.h \ + ../DataStr/avl.h GeoInterpolation.h +gmshEdge.o: gmshEdge.cpp GFace.h GPoint.h GEntity.h Range.h SPoint3.h \ + SBoundingBox3d.h ../Common/GmshDefines.h GEdgeLoop.h GEdge.h GVertex.h \ + MVertex.h SPoint2.h SVector3.h MElement.h MEdge.h ../Common/Hash.h \ + MFace.h ../Numeric/Numeric.h ../Common/Context.h ../DataStr/List.h \ + ExtrudeParams.h Pair.h gmshEdge.h Geo.h ../DataStr/Tree.h \ + ../DataStr/avl.h gmshVertex.h GeoInterpolation.h gmshFace.o: gmshFace.cpp GModel.h GVertex.h GEntity.h Range.h SPoint3.h \ SBoundingBox3d.h ../Common/GmshDefines.h MVertex.h GPoint.h SPoint2.h \ GEdge.h SVector3.h MElement.h MEdge.h ../Common/Hash.h MFace.h \ @@ -239,7 +245,7 @@ MVertex.o: MVertex.cpp MVertex.h SPoint3.h MElement.o: MElement.cpp MElement.h ../Common/GmshDefines.h MVertex.h \ SPoint3.h MEdge.h SVector3.h ../Common/Hash.h MFace.h \ ../Numeric/Numeric.h ../Common/Context.h ../DataStr/List.h GEntity.h \ - Range.h SBoundingBox3d.h + Range.h SBoundingBox3d.h ../Common/Message.h SVector3.o: SVector3.cpp SVector3.h SPoint3.h projectionFace.o: projectionFace.cpp projectionFace.h GFace.h GPoint.h \ GEntity.h Range.h SPoint3.h SBoundingBox3d.h ../Common/GmshDefines.h \ diff --git a/Geo/fourierFace.h b/Geo/fourierFace.h index 4e1069fa79c5f9822cbeaa2d5bc3d56957b14007..9a9ecb57524fb929dd280f4fffc1e567cfef250f 100644 --- a/Geo/fourierFace.h +++ b/Geo/fourierFace.h @@ -60,6 +60,9 @@ class fourierFace : public GFace { fourierFace(GModel *m, int num); fourierFace(GFace *f, std::vector<MVertex*> &loop, std::vector<MVertex*> &hole); virtual ~fourierFace(); + + void meshBoundary(); + Range<double> parBounds(int i) const; virtual int paramDegeneracies(int dir, double *par) { return 0; } diff --git a/Mesh/Makefile b/Mesh/Makefile index 521ae19c41683747028768429b3d568b18e33e18..3e62ac0a87b54a467770b76a6474a89a5fc62edc 100644 --- a/Mesh/Makefile +++ b/Mesh/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.157 2006-12-20 15:50:57 remacle Exp $ +# $Id: Makefile,v 1.158 2006-12-21 17:10:15 geuzaine Exp $ # # Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle # @@ -38,7 +38,6 @@ SRC = Generator.cpp \ meshGFaceExtruded.cpp \ meshGRegion.cpp \ meshGRegionDelaunayInsertion.cpp \ - meshGFaceDelaunayInsertion.cpp \ meshGRegionTransfinite.cpp \ meshGRegionExtruded.cpp \ DivideAndConquer.cpp \ diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp index fdb226e9a4dd33869b766a5a5bd5cf19ba34a91b..2cdc22bdee303c899aed43a62f81b52a1fa606cd 100644 --- a/Mesh/meshGFace.cpp +++ b/Mesh/meshGFace.cpp @@ -1,4 +1,4 @@ -// $Id: meshGFace.cpp,v 1.44 2006-12-21 09:33:41 remacle Exp $ +// $Id: meshGFace.cpp,v 1.45 2006-12-21 17:10:15 geuzaine Exp $ // // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle // @@ -580,37 +580,38 @@ bool gmsh2DMeshGenerator ( GFace *gf ) // fprintf(fdeb,"surface %d\n" ,gf->tag()); int count = 0; SBoundingBox3d bbox; - while(itv != all_vertices.end()) - { - MVertex *here = *itv; - SPoint2 param; - if (here->onWhat()->dim() == 0) - { - GVertex *gv = (GVertex*)here->onWhat(); - param=gv->reparamOnFace (gf,1); - } - else if (here->onWhat()->dim() == 1) - { - GEdge *ge = (GEdge*)here->onWhat(); - double UU; - here->getParameter(0,UU); - param=ge->reparamOnFace (gf,UU,1); - } + while(itv != all_vertices.end()){ + MVertex *here = *itv; + SPoint2 param; + if(here->onWhat()->dim() == 0){ + GVertex *gv = (GVertex*)here->onWhat(); + param = gv->reparamOnFace(gf,1); + } + else if(here->onWhat()->dim() == 1){ + GEdge *ge = (GEdge*)here->onWhat(); + double UU; + here->getParameter(0, UU); + param = ge->reparamOnFace(gf, UU, 1); + } + else{ + double UU, VV; + if(here->onWhat() == gf && here->getParameter(0, UU) && here->getParameter(1, VV)) + param = SPoint2(UU, VV); else - param = gf->parFromPoint (SPoint3(here->x(),here->y(),here->z())); - // fprintf(fdeb,"%d %g %g %g\n" ,here->getNum(),here->x(),here->y(),here->z()); - U_[count] = param.x(); - V_[count] = param.y(); - (*itv)->setNum(count); - numbered_vertices[(*itv)->getNum()] = *itv; - bbox += SPoint3 ( param.x(), param.y() , 0); - count ++; - ++itv; + param = gf->parFromPoint(SPoint3(here->x(), here->y(), here->z())); } - + // fprintf(fdeb,"%d %g %g %g\n" ,here->getNum(),here->x(),here->y(),here->z()); + U_[count] = param.x(); + V_[count] = param.y(); + (*itv)->setNum(count); + numbered_vertices[(*itv)->getNum()] = *itv; + bbox += SPoint3 ( param.x(), param.y() , 0); + count ++; + ++itv; + } + // fclose (fdeb); - // compute the bounding box in parametric space // I do not have SBoundingBox, so I use a 3D one... // At the same time, number the vertices locally @@ -719,7 +720,7 @@ bool gmsh2DMeshGenerator ( GFace *gf ) { if (!recover_medge ( m, *it)) { - Msg(WARNING,"Face not meshed"); + Msg(GERROR,"Face not meshed"); return false; } ++it; diff --git a/Mesh/meshGFaceTransfinite.cpp b/Mesh/meshGFaceTransfinite.cpp index d250c8e2e8aeca03c5697dbfd78c0866e00a19b5..7e4e213af2ce4e19317d378562ebeaa54d71fc51 100644 --- a/Mesh/meshGFaceTransfinite.cpp +++ b/Mesh/meshGFaceTransfinite.cpp @@ -1,4 +1,4 @@ -// $Id: meshGFaceTransfinite.cpp,v 1.14 2006-12-21 09:33:41 remacle Exp $ +// $Id: meshGFaceTransfinite.cpp,v 1.15 2006-12-21 17:10:15 geuzaine Exp $ // // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle // @@ -103,23 +103,24 @@ int MeshTransfiniteSurface( GFace *gf) return 0; } } - SPoint2 param; - if (v->onWhat()->dim() == 0) - { - GVertex *gv = (GVertex*)v->onWhat(); - param=gv->reparamOnFace (gf,1); - } - else if (v->onWhat()->dim() == 1) - { - GEdge *ge = (GEdge*)v->onWhat(); - double UU; - v->getParameter(0,UU); - param=ge->reparamOnFace (gf,UU,1); - } - else - param = gf->parFromPoint (SPoint3(v->x(),v->y(),v->z())); - + if(v->onWhat()->dim() == 0){ + GVertex *gv = (GVertex*)v->onWhat(); + param = gv->reparamOnFace(gf, 1); + } + else if(v->onWhat()->dim() == 1){ + GEdge *ge = (GEdge*)v->onWhat(); + double UU; + v->getParameter(0, UU); + param = ge->reparamOnFace(gf, UU, 1); + } + else{ + double UU, VV; + if(v->onWhat() == gf && v->getParameter(0, UU) && v->getParameter(1, VV)) + param = SPoint2(UU, VV); + else + param = gf->parFromPoint(SPoint3(v->x(), v->y(), v->z())); + } U.push_back(param.x()); V.push_back(param.y()); } @@ -248,29 +249,8 @@ int MeshTransfiniteSurface( GFace *gf) int iP1 = N1 + i; int iP2 = N2 + j; int iP3 = ((N3 + N2) - i) % m_vertices.size(); -#if 0 // FIXME: this is buggy, so let's just do it in real space instead for now double Up = TRAN_TRI(U[iP1], U[iP2], U[iP3], UC1, UC2, UC3, u, v); double Vp = TRAN_TRI(V[iP1], V[iP2], V[iP3], VC1, VC2, VC3, u, v); -#else - double xp = TRAN_TRI(m_vertices[iP1]->x(), m_vertices[iP2]->x(), - m_vertices[iP3]->x(), m_vertices[N1]->x(), - m_vertices[N2]->x(), m_vertices[N3]->x(), u, v); - double yp = TRAN_TRI(m_vertices[iP1]->y(), m_vertices[iP2]->y(), - m_vertices[iP3]->y(), m_vertices[N1]->y(), - m_vertices[N2]->y(), m_vertices[N3]->y(), u, v); - double zp = TRAN_TRI(m_vertices[iP1]->z(), m_vertices[iP2]->z(), - m_vertices[iP3]->z(), m_vertices[N1]->z(), - m_vertices[N2]->z(), m_vertices[N3]->z(), u, v); - double Up, Vp; - if(gf->geomType() == GEntity::Plane){ - SPoint2 param = gf->parFromPoint(SPoint3(xp, yp, zp)); - Up = param.x(); - Vp = param.y(); - } - else{ // xp, yp, zp is usually not on the surface - gf->XYZtoUV(xp, yp, zp, Up, Vp, 1.0, false); - } -#endif GPoint gp = gf->point(SPoint2(Up, Vp)); MFaceVertex *newv = new MFaceVertex(gp.x(), gp.y(), gp.z(), gf, Up, Vp); gf->mesh_vertices.push_back(newv); diff --git a/Parser/OpenFile.cpp b/Parser/OpenFile.cpp index 5f6ba17acb37518d69cb789ee7a0085027d1ed9e..a6cd9e74616962c4e49367c206197af274722c24 100644 --- a/Parser/OpenFile.cpp +++ b/Parser/OpenFile.cpp @@ -1,4 +1,4 @@ -// $Id: OpenFile.cpp,v 1.135 2006-12-16 18:38:52 geuzaine Exp $ +// $Id: OpenFile.cpp,v 1.136 2006-12-21 17:10:15 geuzaine Exp $ // // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle // @@ -248,7 +248,7 @@ void SetProjectName(char *name) int MergeFile(char *name, int warn_if_missing) { #if defined(HAVE_FOURIER_MODEL) - if(!strcmp(name, "falcon")){ + if(!strcmp(name, "falcon") || !strcmp(name, "ship")){ GMODEL->readFourier(name); SetBoundingBox(); CTX.mesh.changed = ENT_ALL; diff --git a/benchmarks/2d/transfinite_tri_ugly_fix.geo b/benchmarks/2d/transfinite_tri_ugly_fix.geo index d10c640a424d8c0c64e5c4ebe07a8bccfee1b097..a511ae153a244c2895d191e897686e5fbdf2a32f 100644 --- a/benchmarks/2d/transfinite_tri_ugly_fix.geo +++ b/benchmarks/2d/transfinite_tri_ugly_fix.geo @@ -10,6 +10,7 @@ Line Loop(4) = {1,-3,-2}; Plane Surface(5) = {4}; Transfinite Line{1,2,3} = 20; +//Transfinite Surface{5} = {3,1,2}; //Transfinite Surface{5} = {2,1,3}; Transfinite Surface{5} = {1,2,3}; diff --git a/doc/texinfo/gmsh.texi b/doc/texinfo/gmsh.texi index 1a74f5b5d9203336f30421bdebfd95c8d21a2979..7d5382934c264262b7aa4a6f9e6ebade86a63558 100644 --- a/doc/texinfo/gmsh.texi +++ b/doc/texinfo/gmsh.texi @@ -1,5 +1,5 @@ \input texinfo.tex @c -*-texinfo-*- -@c $Id: gmsh.texi,v 1.223 2006-12-03 20:41:46 geuzaine Exp $ +@c $Id: gmsh.texi,v 1.224 2006-12-21 17:10:15 geuzaine Exp $ @c @c Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle @c @@ -314,12 +314,14 @@ modules is given hereafter. @node Geometry, Mesh, Overview, Overview @section Geometry: geometrical entity definition -Geometries are created in a bottom-up flow by successively defining points, +Gmsh uses a boundary representation (``b-rep'') to describe geometries. +Models are created in a bottom-up flow by successively defining points, oriented lines (line segments, circles, ellipses, splines, @dots{}), -oriented surfaces (plane surfaces, ruled surfaces, triangulated surfaces, -@dots{}) and volumes. Compound groups of geometrical entities can be -defined, based on these elementary geometric entities. Gmsh's scripting -language allows all geometrical entities to be fully parameterized. +oriented surfaces (plane surfaces, ruled surfaces, triangulated +surfaces, @dots{}) and volumes. Compound groups of geometrical entities +(called ``physical groups'') can also be defined, based on these +elementary geometric entities. Gmsh's scripting language allows all +geometrical entities to be fully parameterized. @c ------------------------------------------------------------------------- @c Mesh: finite element mesh generation @@ -329,74 +331,54 @@ language allows all geometrical entities to be fully parameterized. @section Mesh: finite element mesh generation A finite element mesh is a tessellation of a given subset of the -three-dimensional space by elementary geometrical elements of various shapes -(in Gmsh's case: lines, triangles, quadrangles, tetrahedra, prisms, -hexahedra and pyramids), arranged in such a way that if two of them -intersect, they do so along a face, an edge or a node, and never -otherwise. All the finite element meshes produced by Gmsh are considered as -``unstructured'', even if they were generated in a ``structured'' way -(e.g., by extrusion). This implies that the elementary geometrical elements -are defined only by an ordered list of their nodes but that no predefined -order relation is assumed between any two elements. - -The mesh generation is performed in the same bottom-up flow as the geometry -creation: lines are discretized first; the mesh of the lines is then used to -mesh the surfaces; then the mesh of the surfaces is used to mesh the -volumes. In this process, the mesh of an entity is only constrained by the -mesh of its boundary@footnote{For example, in three dimensions: +three-dimensional space by elementary geometrical elements of various +shapes (in Gmsh's case: lines, triangles, quadrangles, tetrahedra, +prisms, hexahedra and pyramids), arranged in such a way that if two of +them intersect, they do so along a face, an edge or a node, and never +otherwise. All the finite element meshes produced by Gmsh are considered +as ``unstructured'', even if they were generated in a ``structured'' way +(e.g., by extrusion). This implies that the elementary geometrical +elements are defined only by an ordered list of their nodes but that no +predefined order relation is assumed between any two elements. + +The mesh generation is performed in the same bottom-up flow as the +geometry creation: lines are discretized first; the mesh of the lines is +then used to mesh the surfaces; then the mesh of the surfaces is used to +mesh the volumes. In this process, the mesh of an entity is only +constrained by the mesh of its boundary@footnote{For example, in three +dimensions: @itemize @bullet @item the triangles discretizing a surface will be forced to be faces of -tetrahedra in the final 3D mesh only if the surface is part of the boundary -of a volume; +tetrahedra in the final 3D mesh only if the surface is part of the +boundary of a volume; @item the line elements discretizing a curve will be forced to be edges of -tetrahedra in the final 3D mesh only if the curve is part of the boundary of -a surface, itself part of the boundary of a volume; +tetrahedra in the final 3D mesh only if the curve is part of the +boundary of a surface, itself part of the boundary of a volume; @item -a single node discretizing a point in the middle of a volume will be forced -to be a vertex of one of the tetrahedra in the final 3D mesh only if this -point is connected to a curve, itself part of the boundary of a surface, -itself part of the boundary of a volume... +a single node discretizing a point in the middle of a volume will be +forced to be a vertex of one of the tetrahedra in the final 3D mesh only +if this point is connected to a curve, itself part of the boundary of a +surface, itself part of the boundary of a volume... @end itemize -}. This automatically assures the conformity of the mesh when, for example, -two surfaces share a common line. But this also implies that the -discretization of an ``isolated'' (@var{n}-1)-th dimensional entity inside -an @var{n}-th dimensional entity does @emph{not} constrain the @var{n}-th -dimensional mesh. Every meshing step is constrained by the characteristic -length field, which can be uniform, specified by characteristic lengths -associated with elementary geometrical entities, or associated with another -mesh (the background mesh). +}. This automatically assures the conformity of the mesh when, for +example, two surfaces share a common line. But this also implies that +the discretization of an ``isolated'' (@var{n}-1)-th dimensional entity +inside an @var{n}-th dimensional entity does @emph{not} constrain the +@var{n}-th dimensional mesh. Every meshing step is constrained by the +characteristic length field, which can be uniform, specified by +characteristic lengths associated with elementary geometrical entities, +or associated with another mesh (the ``background mesh''). For each meshing step, all structured mesh directives are executed first, and serve as additional constraints for the unstructured parts @footnote{Note that mixing structured volume grids with unstructured volume grids generated with the default 3D isotropic Delaunay algorithm can result, in certain cases, to non-conform surface meshes on their -shared boudary. If this happens, you may consider using the Netgen -algorithm for the unstructured part.}. The implemented Delaunay -algorithm is subdivided in the following five steps for surface/volume -discretization: - -@enumerate -@item -trivial meshing of a box including the convex polygon/polyhedron defined by -the boundary nodes resulting from the discretization of the lines/surfaces; -@item -creation of the initial mesh by insertion of all the nodes on the -lines/surfaces thanks to the Bowyer algorithm; -@item -boundary restoration to force all the edges/faces of the lines/surfaces to -be present in the initial mesh; -@item -suppression of all the unwanted triangles/tetrahedra (in particular those -containing the nodes of the initial box); -@item -insertion of new nodes by the Bowyer algorithm until the characteristic size -of each simplex is lower or equal to the characteristic length field -evaluated at the center of its circumscribed circle/sphere. -@end enumerate +shared boundary. If this happens, you may consider using the Netgen +algorithm for the unstructured part.}. @c ------------------------------------------------------------------------- @c Solver: external solver interface @@ -405,13 +387,13 @@ evaluated at the center of its circumscribed circle/sphere. @node Solver, Post-processing, Mesh, Overview @section Solver: external solver interface -External solvers can be interfaced with Gmsh through Unix or TCP/IP sockets, -which permits to easily launch external computations and to collect and -exploit the simulation results within Gmsh's post-processing module. The -default solver interfaced with Gmsh is GetDP -(@uref{http://www.geuz.org/getdp/}). Small examples of solvers written in C, -C++, Perl and Python are available in the source distribution (in the -@file{utils/solvers/} directory). +External solvers can be interfaced with Gmsh through Unix or TCP/IP +sockets, which permits to launch external computations and to collect +and process the results directly from within Gmsh's post-processing +module. The default solver interfaced with Gmsh is GetDP +(@uref{http://www.geuz.org/getdp/}). Examples on how to interface +solvers written in C, C++, Perl and Python are available in the source +distribution (in the @file{utils/solvers/} directory). @c ------------------------------------------------------------------------- @c Post-processing: scalar, vector and tensor field visualization @@ -420,17 +402,18 @@ C++, Perl and Python are available in the source distribution (in the @node Post-processing, What Gmsh is pretty good at, Solver, Overview @section Post-processing: scalar, vector and tensor field visualization -Multiple post-processing scalar, vector or tensor maps can be loaded and -manipulated (globally or individually) along with the geometry and the -mesh. Scalar fields are represented by iso-value lines/surfaces or color -maps, while vector fields are represented by three-dimensional arrows or -displacement maps. Post-processing functions include section computation, -offset, elevation, boundary and component extraction, color map and range -modification, animation, vector graphic output, etc. All post-processing -options can be accessed either interactively or through the input ASCII text -files. Scripting permits to automate all post-processing operations, e.g., -for the creation of animations. User-defined operations can also be -performed on post-processing views through dynamically loadable plugins. +Gmsh can load and manipulate multiple post-processing scalar, vector or +tensor maps along with the geometry and the mesh. Scalar fields are +represented by iso-value lines/surfaces or color maps, while vector +fields are represented by three-dimensional arrows or displacement +maps. Post-processing functions include section computation, offset, +elevation, boundary and component extraction, color map and range +modification, animation, vector graphic output, etc. All the +post-processing options can be accessed either interactively or through +the input ASCII text files. Scripting permits to automate all +post-processing operations, as for example to create +animations. User-defined operations can also be performed on +post-processing views through dynamically loadable plugins. @c ------------------------------------------------------------------------- @c What Gmsh is pretty good at... @@ -455,6 +438,8 @@ parameterize these geometries. Gmsh's scripting language enables all commands and command arguments to depend on previous calculations (see @ref{Expressions}, and @ref{Geometry commands}); @item +import complex models in industry-standard formats like STEP or IGES; +@item generate 1D, 2D and 3D simplicial (i.e., using line segments, triangles and tetrahedra) finite element meshes. The performance of the 1D and 2D algorithms is pretty good; the 3D algorithm is still experimental and slow @@ -480,10 +465,10 @@ PostScript, LaTeX, PNG, JPEG, @dots{} (@pxref{General options}); @item generate complex animations (see @ref{General tools}, and @ref{t8.geo}); @item -run on low end machines and/or machines with no graphic system. Gmsh can be -compiled with or without the graphical user interface, and all versions can -be used either interactively or not, directly from the command line -(@pxref{Running Gmsh}); +run on low end machines and/or machines with no graphical +interface. Gmsh can be compiled with or without the GUI, and all +versions can be used either interactively or directly from the command +line (@pxref{Running Gmsh}); @item configure your preferred options. Gmsh has a large number of configuration options that can be set interactively using the GUI, scattered inside @@ -509,11 +494,12 @@ also some (a lot of?) weaknesses: @itemize @bullet @item -the bottom-up approach for describing geometries can become inconvenient for +the b-rep approach for describing geometries can become inconvenient for complex models; @item -there is no support for NURBS and only very limited support for trimmed -surfaces; +there is no support for Nurbs and only very limited support for trimmed +surfaces in Gmsh's scripting language (however you can import STEP or +IGES models with such features); @item Gmsh is not primarily a structured mesh generator: no automatic quadrilateral or hexahedral meshing algorithm is provided. If you want