Skip to content
Snippets Groups Projects
Commit d5dcebc0 authored by Christophe Geuzaine's avatar Christophe Geuzaine
Browse files

fix high order mesh for boundary layers

parent e71021eb
No related branches found
No related tags found
No related merge requests found
...@@ -226,6 +226,10 @@ static void getEdgeVertices(GEdge *ge, MElement *ele, std::vector<MVertex*> &ve, ...@@ -226,6 +226,10 @@ static void getEdgeVertices(GEdge *ge, MElement *ele, std::vector<MVertex*> &ve,
int nPts = 1, gmshHighOrderSmoother *displ2D = 0, int nPts = 1, gmshHighOrderSmoother *displ2D = 0,
gmshHighOrderSmoother *displ3D = 0) gmshHighOrderSmoother *displ3D = 0)
{ {
if(ge->geomType() == GEntity::DiscreteCurve ||
ge->geomType() == GEntity::BoundaryLayerCurve)
linear = true;
for(int i = 0; i < ele->getNumEdges(); i++){ for(int i = 0; i < ele->getNumEdges(); i++){
MEdge edge = ele->getEdge(i); MEdge edge = ele->getEdge(i);
std::pair<MVertex*, MVertex*> p(edge.getMinVertex(), edge.getMaxVertex()); std::pair<MVertex*, MVertex*> p(edge.getMinVertex(), edge.getMaxVertex());
...@@ -237,42 +241,37 @@ static void getEdgeVertices(GEdge *ge, MElement *ele, std::vector<MVertex*> &ve, ...@@ -237,42 +241,37 @@ static void getEdgeVertices(GEdge *ge, MElement *ele, std::vector<MVertex*> &ve,
} }
else{ else{
MVertex *v0 = edge.getVertex(0), *v1 = edge.getVertex(1); MVertex *v0 = edge.getVertex(0), *v1 = edge.getVertex(1);
double u0 = 0., u1 = 0.; double u0 = 0., u1 = 0., US[100];
bool reparamOK = true; bool reparamOK = true;
if(!linear && ge->geomType() != GEntity::DiscreteCurve && if(!linear){
ge->geomType() != GEntity::BoundaryLayerCurve){
reparamOK &= reparamMeshVertexOnEdge(v0, ge, u0); reparamOK &= reparamMeshVertexOnEdge(v0, ge, u0);
if (ge->periodic(0) && v1 == ge->getEndVertex()->mesh_vertices[0]){ if(ge->periodic(0) && v1 == ge->getEndVertex()->mesh_vertices[0])
Range<double> par = ge->parBounds(0); u1 = ge->parBounds(0).high();
u1 = par.high();
}
else else
reparamOK &= reparamMeshVertexOnEdge(v1, ge, u1); reparamOK &= reparamMeshVertexOnEdge(v1, ge, u1);
if(reparamOK){
double relax = 1.;
while (1){
if(computeEquidistantParameters(ge, u0, u1, nPts + 2, US, relax))
break;
relax /= 2.0;
if(relax < 1.e-2)
break;
}
if(relax < 1.e-2)
Msg::Warning("Failed to compute equidistant parameters (relax = %g)",
relax);
}
} }
double US[100]; std::vector<MVertex*> temp;
if(reparamOK && !linear && ge->geomType() != GEntity::DiscreteCurve){
double relax = 1.;
while (1){
if(computeEquidistantParameters(ge, u0, u1, nPts + 2, US, relax))
break;
relax /= 2.0;
if (relax < 1.e-2)
break;
}
if (relax < 1.e-2)
Msg::Warning("Failed to compute equidistant parameters (relax = %g)",
relax);
}
std::vector<MVertex*> temp;
for(int j = 0; j < nPts; j++){ for(int j = 0; j < nPts; j++){
const double t = (double)(j + 1)/(nPts + 1); const double t = (double)(j + 1)/(nPts + 1);
double uc = (1. - t) * u0 + t * u1; double uc = (1. - t) * u0 + t * u1; // can be wrong, that's ok
MVertex *v; MVertex *v;
if(!reparamOK || linear || ge->geomType() == GEntity::DiscreteCurve || if(linear || !reparamOK || uc < u0 || uc > u1){
uc < u0 || uc > u1){ // need to treat periodic curves properly! // we don't have a (valid) parameter on the curve
SPoint3 pc = edge.interpolate(t); SPoint3 pc = edge.interpolate(t);
v = new MVertex(pc.x(), pc.y(), pc.z(), ge); v = new MVertex(pc.x(), pc.y(), pc.z(), ge);
v->setParameter(0, t);
} }
else { else {
GPoint pc = ge->point(US[j + 1]); GPoint pc = ge->point(US[j + 1]);
...@@ -284,6 +283,7 @@ static void getEdgeVertices(GEdge *ge, MElement *ele, std::vector<MVertex*> &ve, ...@@ -284,6 +283,7 @@ static void getEdgeVertices(GEdge *ge, MElement *ele, std::vector<MVertex*> &ve,
} }
} }
temp.push_back(v); temp.push_back(v);
// this destroys the ordering of the mesh vertices on the edge
ge->mesh_vertices.push_back(v); ge->mesh_vertices.push_back(v);
ve.push_back(v); ve.push_back(v);
} }
...@@ -300,6 +300,10 @@ static void getEdgeVertices(GFace *gf, MElement *ele, std::vector<MVertex*> &ve, ...@@ -300,6 +300,10 @@ static void getEdgeVertices(GFace *gf, MElement *ele, std::vector<MVertex*> &ve,
int nPts = 1, gmshHighOrderSmoother *displ2D = 0, int nPts = 1, gmshHighOrderSmoother *displ2D = 0,
gmshHighOrderSmoother *displ3D = 0) gmshHighOrderSmoother *displ3D = 0)
{ {
if(gf->geomType() == GEntity::DiscreteSurface ||
gf->geomType() == GEntity::BoundaryLayerSurface)
linear = true;
for(int i = 0; i < ele->getNumEdges(); i++){ for(int i = 0; i < ele->getNumEdges(); i++){
MEdge edge = ele->getEdge(i); MEdge edge = ele->getEdge(i);
std::pair<MVertex*, MVertex*> p(edge.getMinVertex(), edge.getMaxVertex()); std::pair<MVertex*, MVertex*> p(edge.getMinVertex(), edge.getMaxVertex());
...@@ -312,27 +316,26 @@ static void getEdgeVertices(GFace *gf, MElement *ele, std::vector<MVertex*> &ve, ...@@ -312,27 +316,26 @@ static void getEdgeVertices(GFace *gf, MElement *ele, std::vector<MVertex*> &ve,
else{ else{
MVertex *v0 = edge.getVertex(0), *v1 = edge.getVertex(1); MVertex *v0 = edge.getVertex(0), *v1 = edge.getVertex(1);
SPoint2 p0, p1; SPoint2 p0, p1;
double US[100], VS[100];
bool reparamOK = true; bool reparamOK = true;
if(!linear && if(!linear){
gf->geomType() != GEntity::DiscreteSurface &&
gf->geomType() != GEntity::BoundaryLayerSurface){
reparamOK = reparamMeshEdgeOnFace(v0, v1, gf, p0, p1); reparamOK = reparamMeshEdgeOnFace(v0, v1, gf, p0, p1);
} if(reparamOK)
double US[100], VS[100]; computeEquidistantParameters(gf, p0[0], p1[0], p0[1], p1[1], nPts + 2,
if(reparamOK && !linear && gf->geomType() != GEntity::DiscreteSurface){ US, VS);
computeEquidistantParameters(gf, p0[0], p1[0], p0[1], p1[1], nPts + 2, US, VS);
} }
std::vector<MVertex*> temp; std::vector<MVertex*> temp;
for(int j = 0; j < nPts; j++){ for(int j = 0; j < nPts; j++){
const double t = (double)(j + 1) / (nPts + 1); const double t = (double)(j + 1) / (nPts + 1);
MVertex *v; MVertex *v;
if(!reparamOK || linear || gf->geomType() == GEntity::DiscreteSurface){ if(linear || !reparamOK){
// we don't have (valid) parameters on the surface
SPoint3 pc = edge.interpolate(t); SPoint3 pc = edge.interpolate(t);
v = new MVertex(pc.x(), pc.y(), pc.z(), gf); v = new MVertex(pc.x(), pc.y(), pc.z(), gf);
} }
else{ else{
GPoint pc = gf->point(US[j+1], VS[j+1]); GPoint pc = gf->point(US[j + 1], VS[j + 1]);
v = new MFaceVertex(pc.x(), pc.y(), pc.z(), gf, US[j+1], VS[j+1]); v = new MFaceVertex(pc.x(), pc.y(), pc.z(), gf, US[j + 1], VS[j + 1]);
if (displ3D){ if (displ3D){
SPoint3 pc2 = edge.interpolate(t); SPoint3 pc2 = edge.interpolate(t);
displ3D->add(v, SVector3(pc2.x(), pc2.y(), pc2.z())); displ3D->add(v, SVector3(pc2.x(), pc2.y(), pc2.z()));
...@@ -390,6 +393,10 @@ static void getFaceVertices(GFace *gf, MElement *incomplete, MElement *ele, ...@@ -390,6 +393,10 @@ static void getFaceVertices(GFace *gf, MElement *incomplete, MElement *ele,
bool linear, int nPts = 1, gmshHighOrderSmoother *displ2D = 0, bool linear, int nPts = 1, gmshHighOrderSmoother *displ2D = 0,
gmshHighOrderSmoother *displ3D = 0) gmshHighOrderSmoother *displ3D = 0)
{ {
if(gf->geomType() == GEntity::DiscreteSurface ||
gf->geomType() == GEntity::BoundaryLayerSurface)
linear = true;
Double_Matrix points; Double_Matrix points;
int start = 0; int start = 0;
...@@ -421,19 +428,16 @@ static void getFaceVertices(GFace *gf, MElement *incomplete, MElement *ele, ...@@ -421,19 +428,16 @@ static void getFaceVertices(GFace *gf, MElement *incomplete, MElement *ele,
std::vector<MVertex*> &vtcs = faceVertices[face]; std::vector<MVertex*> &vtcs = faceVertices[face];
SPoint2 pts[20]; SPoint2 pts[20];
bool reparamOK = true; bool reparamOK = true;
if(!linear && if(!linear){
gf->geomType() != GEntity::DiscreteSurface && for(int k = 0; k < incomplete->getNumVertices(); k++)
gf->geomType() != GEntity::BoundaryLayerSurface){
for (int k = 0; k < incomplete->getNumVertices(); k++){
reparamOK &= reparamMeshVertexOnFace(incomplete->getVertex(k), gf, pts[k]); reparamOK &= reparamMeshVertexOnFace(incomplete->getVertex(k), gf, pts[k]);
}
} }
if(face.getNumVertices() == 3 && nPts > 1){ // tri face if(face.getNumVertices() == 3 && nPts > 1){ // tri face
for(int k = start; k < points.size1(); k++){ for(int k = start; k < points.size1(); k++){
MVertex *v; MVertex *v;
const double t1 = points(k, 0); const double t1 = points(k, 0);
const double t2 = points(k, 1); const double t2 = points(k, 1);
if(linear || gf->geomType() == GEntity::DiscreteSurface){ if(linear){
SPoint3 pc = face.interpolate(t1, t2); SPoint3 pc = face.interpolate(t1, t2);
v = new MVertex(pc.x(), pc.y(), pc.z(), gf); v = new MVertex(pc.x(), pc.y(), pc.z(), gf);
} }
...@@ -463,7 +467,7 @@ static void getFaceVertices(GFace *gf, MElement *incomplete, MElement *ele, ...@@ -463,7 +467,7 @@ static void getFaceVertices(GFace *gf, MElement *incomplete, MElement *ele,
else{ else{
v = new MVertex(X, Y, Z, gf); v = new MVertex(X, Y, Z, gf);
} }
if (displ3D){ if(displ3D){
SPoint3 pc2 = face.interpolate(t1, t2); SPoint3 pc2 = face.interpolate(t1, t2);
displ3D->add(v, SVector3(pc2.x(), pc2.y(), pc2.z())); displ3D->add(v, SVector3(pc2.x(), pc2.y(), pc2.z()));
} }
...@@ -481,7 +485,7 @@ static void getFaceVertices(GFace *gf, MElement *incomplete, MElement *ele, ...@@ -481,7 +485,7 @@ static void getFaceVertices(GFace *gf, MElement *incomplete, MElement *ele,
// parameters are between -1 and 1 // parameters are between -1 and 1
double t1 = 2. * (double)(j + 1) / (nPts + 1) - 1.; double t1 = 2. * (double)(j + 1) / (nPts + 1) - 1.;
double t2 = 2. * (double)(k + 1) / (nPts + 1) - 1.; double t2 = 2. * (double)(k + 1) / (nPts + 1) - 1.;
if(!reparamOK || linear || gf->geomType() == GEntity::DiscreteSurface){ if(linear || !reparamOK){
SPoint3 pc = face.interpolate(t1, t2); SPoint3 pc = face.interpolate(t1, t2);
v = new MVertex(pc.x(), pc.y(), pc.z(), gf); v = new MVertex(pc.x(), pc.y(), pc.z(), gf);
} }
...@@ -697,7 +701,7 @@ static void setHighOrder(GFace *gf, edgeContainer &edgeVertices, ...@@ -697,7 +701,7 @@ static void setHighOrder(GFace *gf, edgeContainer &edgeVertices,
for(unsigned int i = 0; i < gf->triangles.size(); i++){ for(unsigned int i = 0; i < gf->triangles.size(); i++){
MTriangle *t = gf->triangles[i]; MTriangle *t = gf->triangles[i];
std::vector<MVertex*> ve, vf; std::vector<MVertex*> ve, vf;
getEdgeVertices(gf, t, ve, edgeVertices, linear, nPts,displ2D,displ3D); getEdgeVertices(gf, t, ve, edgeVertices, linear, nPts, displ2D, displ3D);
if(nPts == 1){ if(nPts == 1){
triangles2.push_back triangles2.push_back
(new MTriangle6(t->getVertex(0), t->getVertex(1), t->getVertex(2), (new MTriangle6(t->getVertex(0), t->getVertex(1), t->getVertex(2),
......
...@@ -12,6 +12,17 @@ ...@@ -12,6 +12,17 @@
#include "GmshMessage.h" #include "GmshMessage.h"
#include "OS.h" #include "OS.h"
class MVertexLessParam{
public:
bool operator()(const MVertex *v1, const MVertex *v2) const
{
double u1 = 0., u2 = 1.;
v1->getParameter(0, u1);
v2->getParameter(0, u2);
return u1 < u2;
}
};
static void Subdivide(GEdge *ge) static void Subdivide(GEdge *ge)
{ {
std::vector<MLine*> lines2; std::vector<MLine*> lines2;
...@@ -25,6 +36,9 @@ static void Subdivide(GEdge *ge) ...@@ -25,6 +36,9 @@ static void Subdivide(GEdge *ge)
} }
ge->lines = lines2; ge->lines = lines2;
// 2nd order meshing destroyed the ordering of the vertices on the edge
std::sort(ge->mesh_vertices.begin(), ge->mesh_vertices.end(),
MVertexLessParam());
for(unsigned int i = 0; i < ge->mesh_vertices.size(); i++) for(unsigned int i = 0; i < ge->mesh_vertices.size(); i++)
ge->mesh_vertices[i]->setPolynomialOrder(1); ge->mesh_vertices[i]->setPolynomialOrder(1);
ge->deleteVertexArrays(); ge->deleteVertexArrays();
......
...@@ -104,10 +104,8 @@ int MeshTransfiniteSurface(GFace *gf) ...@@ -104,10 +104,8 @@ int MeshTransfiniteSurface(GFace *gf)
// get the indices of the interpolation corners as well as the u,v // get the indices of the interpolation corners as well as the u,v
// coordinates of all the boundary vertices // coordinates of all the boundary vertices
int iCorner = 0; int iCorner = 0, N[4] = {0, 0, 0, 0};
int N[4] = {0, 0, 0, 0}; std::vector<double> U, V;
std::vector<double> U;
std::vector<double> V;
for(unsigned int i = 0; i < m_vertices.size(); i++){ for(unsigned int i = 0; i < m_vertices.size(); i++){
MVertex *v = m_vertices[i]; MVertex *v = m_vertices[i];
if(v == corners[0] || v == corners[1] || v == corners[2] || if(v == corners[0] || v == corners[1] || v == corners[2] ||
...@@ -119,38 +117,15 @@ int MeshTransfiniteSurface(GFace *gf) ...@@ -119,38 +117,15 @@ int MeshTransfiniteSurface(GFace *gf)
} }
} }
SPoint2 param; SPoint2 param;
if(v->onWhat()->dim() == 0){ reparamMeshVertexOnFace(v, gf, param);
GVertex *gv = (GVertex*)v->onWhat(); U.push_back(param[0]);
param = gv->reparamOnFace(gf, 1); V.push_back(param[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());
} }
int N1 = N[0]; int N1 = N[0], N2 = N[1], N3 = N[2], N4 = N[3];
int N2 = N[1]; int L = N2 - N1, H = N3 - N2;
int N3 = N[2];
int N4 = N[3];
int L = N2 - N1;
int H = N3 - N2;
if(corners.size () == 4){ if(corners.size () == 4){
int Lb = N4 - N3; int Lb = N4 - N3, Hb = m_vertices.size() - N4;
int Hb = m_vertices.size() - N4;
if(Lb != L || Hb != H){ if(Lb != L || Hb != H){
Msg::Error("Surface %d cannot be meshed using the transfinite algo", Msg::Error("Surface %d cannot be meshed using the transfinite algo",
gf->tag()); gf->tag());
...@@ -166,10 +141,8 @@ int MeshTransfiniteSurface(GFace *gf) ...@@ -166,10 +141,8 @@ int MeshTransfiniteSurface(GFace *gf)
} }
} }
std::vector<double> lengths_i; std::vector<double> lengths_i, lengths_j;
std::vector<double> lengths_j; double L_i = 0, L_j = 0;
double L_i = 0;
double L_j = 0;
lengths_i.push_back(0.); lengths_i.push_back(0.);
lengths_j.push_back(0.); lengths_j.push_back(0.);
for(int i = 0; i < L; i++){ for(int i = 0; i < L; i++){
...@@ -230,12 +203,8 @@ int MeshTransfiniteSurface(GFace *gf) ...@@ -230,12 +203,8 @@ int MeshTransfiniteSurface(GFace *gf)
} }
} }
double UC1 = U[N1]; double UC1 = U[N1], UC2 = U[N2], UC3 = U[N3];
double UC2 = U[N2]; double VC1 = V[N1], VC2 = V[N2], VC3 = V[N3];
double UC3 = U[N3];
double VC1 = V[N1];
double VC2 = V[N2];
double VC3 = V[N3];
//create points using transfinite interpolation //create points using transfinite interpolation
if(corners.size() == 4){ if(corners.size() == 4){
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment