Forked from
gmsh / gmsh
14180 commits behind the upstream repository.
-
Tuomas Karna authored
meshPartitionOptions::partitionByExtrusion assigns all extruded elements to the same partition as the source element
Tuomas Karna authoredmeshPartitionOptions::partitionByExtrusion assigns all extruded elements to the same partition as the source element
meshGFaceExtruded.cpp 8.62 KiB
// Gmsh - Copyright (C) 1997-2010 C. Geuzaine, J.-F. Remacle
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to <gmsh@geuz.org>.
#include <set>
#include "GModel.h"
#include "MLine.h"
#include "MTriangle.h"
#include "MQuadrangle.h"
#include "ExtrudeParams.h"
#include "Context.h"
#include "GmshMessage.h"
static void addTriangle(MVertex* v1, MVertex* v2, MVertex* v3, GFace *to, MElement* source) {
MTriangle* newTri = new MTriangle(v1, v2, v3);
to->triangles.push_back(newTri);
to->meshAttributes.extrude->elementMap.addExtrudedElem((MElement*)source,(MElement*)newTri);
}
static void addQuadrangle(MVertex* v1, MVertex* v2, MVertex* v3, MVertex* v4, GFace *to, MElement* source) {
MQuadrangle* newQuad = new MQuadrangle(v1, v2, v3, v4);
to->quadrangles.push_back(newQuad);
to->meshAttributes.extrude->elementMap.addExtrudedElem((MElement*)source,(MElement*)newQuad);
}
static void createQuaTri(std::vector<MVertex*> &v, GFace *to,
std::set<std::pair<MVertex*, MVertex*> > *constrainedEdges,MLine* source)
{
ExtrudeParams *ep = to->meshAttributes.extrude;
if(v[0] == v[1] || v[1] == v[3])
addTriangle(v[0], v[3], v[2],to,source);
else if(v[0] == v[2] || v[2] == v[3])
addTriangle(v[0], v[1], v[3],to,source);
else if(v[0] == v[3] || v[1] == v[2])
Msg::Error("Uncoherent extruded quadrangle in surface %d", to->tag());
else{
if(ep->mesh.Recombine){
addQuadrangle(v[0], v[1], v[3], v[2],to,source);
}
else if(!constrainedEdges){
addTriangle(v[0], v[1], v[3],to,source);
addTriangle(v[0], v[3], v[2],to,source);
}
else{
std::pair<MVertex*, MVertex*> p(std::min(v[1], v[2]), std::max(v[1], v[2]));
if(constrainedEdges->count(p)){
addTriangle(v[2], v[1], v[0],to,source);
addTriangle(v[2], v[3], v[1],to,source);
}
else{
addTriangle(v[2], v[3], v[0],to,source);
addTriangle(v[0], v[3], v[1],to,source);
}
}
}
}
static void extrudeMesh(GEdge *from, GFace *to,
std::set<MVertex*, MVertexLessThanLexicographic> &pos,
std::set<std::pair<MVertex*, MVertex*> > *constrainedEdges)
{
ExtrudeParams *ep = to->meshAttributes.extrude;
// create vertices (if the edges are constrained, they already exist)
if(!constrainedEdges){
for(unsigned int i = 0; i < from->mesh_vertices.size(); i++){
MVertex *v = from->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);
}
}
}
}
}
// 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)
std::set<MVertex*, MVertexLessThanLexicographic>::iterator itp;
for(unsigned int i = 0; i < from->lines.size(); i++){
MVertex *v0 = from->lines[i]->getVertex(0);
MVertex *v1 = from->lines[i]->getVertex(1);
for(int j = 0; j < ep->mesh.NbLayer; j++) {
for(int k = 0; k < ep->mesh.NbElmLayer[j]; k++) {
std::vector<MVertex*> verts;
double x[4] = {v0->x(), v1->x(), v0->x(), v1->x()};
double y[4] = {v0->y(), v1->y(), v0->y(), v1->y()};
double z[4] = {v0->z(), v1->z(), v0->z(), v1->z()};
for(int p = 0; p < 2; p++){
ep->Extrude(j, k, x[p], y[p], z[p]);
ep->Extrude(j, k + 1, x[p + 2], y[p + 2], z[p + 2]);
}
for(int p = 0; p < 4; p++){
MVertex tmp(x[p], y[p], z[p], 0, -1);
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());
return;
}
verts.push_back(*itp);
}
createQuaTri(verts, to, constrainedEdges,from->lines[i]);
}
}
}
}
static void copyMesh(GFace *from, GFace *to,
std::set<MVertex*, MVertexLessThanLexicographic> &pos)
{
ExtrudeParams *ep = to->meshAttributes.extrude;
// create vertices
for(unsigned int i = 0; i < from->mesh_vertices.size(); i++){
MVertex *v = from->mesh_vertices[i];
double x = v->x(), y = v->y(), z = v->z();
ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1],
x, y, z);
MVertex *newv = new MVertex(x, y, z, to);
to->mesh_vertices.push_back(newv);
pos.insert(newv);
}
// create elements
std::set<MVertex*, MVertexLessThanLexicographic>::iterator itp;
for(unsigned int i = 0; i < from->triangles.size(); i++){
std::vector<MVertex*> verts;
for(int j = 0; j < 3; j++){
MVertex *v = from->triangles[i]->getVertex(j);
MVertex tmp(v->x(), v->y(), v->z(), 0, -1);
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());
return;
}
verts.push_back(*itp);
}
addTriangle(verts[0],verts[1],verts[2],to,from->triangles[i]);
}
for(unsigned int i = 0; i < from->quadrangles.size(); i++){
std::vector<MVertex*> verts;
for(int j = 0; j < 4; j++){
MVertex *v = from->quadrangles[i]->getVertex(j);
MVertex tmp(v->x(), v->y(), v->z(), 0, -1);
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());
return;
}
verts.push_back(*itp);
}
addQuadrangle(verts[0],verts[1],verts[2],verts[3],to,from->quadrangles[i]);
}
}
int MeshExtrudedSurface(GFace *gf,
std::set<std::pair<MVertex*, MVertex*> > *constrainedEdges)
{
ExtrudeParams *ep = gf->meshAttributes.extrude;
if(!ep || !ep->mesh.ExtrudeMesh)
return 0;
Msg::StatusBar(2, true, "Meshing surface %d (extruded)", gf->tag());
// build a set with all the vertices on the boundary of the face gf
double old_tol = MVertexLessThanLexicographic::tolerance;
MVertexLessThanLexicographic::tolerance = 1.e-12 * CTX::instance()->lc;
std::set<MVertex*, MVertexLessThanLexicographic> pos;
std::list<GEdge*> edges = gf->edges();
std::list<GEdge*>::iterator it = edges.begin();
while(it != edges.end()){
pos.insert((*it)->mesh_vertices.begin(), (*it)->mesh_vertices.end());
pos.insert((*it)->getBeginVertex()->mesh_vertices.begin(),
(*it)->getBeginVertex()->mesh_vertices.end());
pos.insert((*it)->getEndVertex()->mesh_vertices.begin(),
(*it)->getEndVertex()->mesh_vertices.end());
++it;
}
// if the edges of the mesh are constrained, the vertices already
// exist on the face--so we add them to the set
if(constrainedEdges)
pos.insert(gf->mesh_vertices.begin(), gf->mesh_vertices.end());
if(ep->geo.Mode == EXTRUDED_ENTITY) {
// surface is extruded from a curve
GEdge *from = gf->model()->getEdgeByTag(std::abs(ep->geo.Source));
if(!from){
Msg::Error("Unknown source curve %d for extrusion", ep->geo.Source);
return 0;
}
extrudeMesh(from, gf, pos, constrainedEdges);
}
else {
// surface is a copy of another surface (the "top" of the extrusion)
GFace *from = gf->model()->getFaceByTag(std::abs(ep->geo.Source));
if(!from){
Msg::Error("Unknown source surface %d for extrusion", ep->geo.Source);
return 0;
}
copyMesh(from, gf, pos);
}
MVertexLessThanLexicographic::tolerance = old_tol;
gf->meshStatistics.status = GFace::DONE;
return 1;
}