diff --git a/Mesh/yamakawa.cpp b/Mesh/yamakawa.cpp index 5fe1f8de2c153afb6db5ef21484dd433e435a966..653204bc425a2ea7ba0e117c57f9070edc5a7047 100644 --- a/Mesh/yamakawa.cpp +++ b/Mesh/yamakawa.cpp @@ -2357,6 +2357,30 @@ bool validFace(MVertex *a, MVertex *b, MVertex *c, MVertex *d, std::map<MVertex* } +//Angle between two triangular faces located on the boundary should be high enough +bool PostOp::valid(MPyramid *pyr){ + MVertex *V[4] = {pyr->getVertex(0), pyr->getVertex(1), pyr->getVertex(2), pyr->getVertex(3)}; + MVertex *apex = pyr->getVertex(4); + + if (apex->onWhat()->dim() < 3){ + for (int iP=0; iP<4; iP++) { //loop on pairs of triangles + int nbBndNodes = 0; + if (V[(0+iP)%4]->onWhat()->dim() < 3) nbBndNodes++; + if (V[(1+iP)%4]->onWhat()->dim() < 3) nbBndNodes++; + if (V[(2+iP)%4]->onWhat()->dim() < 3) nbBndNodes++; + if (nbBndNodes == 3){ + SVector3 vec1 = SVector3(V[(0+iP)%4]->x()-apex->x(),V[(0+iP)%4]->y()-apex->y(),V[(0+iP)%4]->z()-apex->z()).unit(); + SVector3 vec2 = SVector3(V[(1+iP)%4]->x()-apex->x(),V[(1+iP)%4]->y()-apex->y(),V[(1+iP)%4]->z()-apex->z()).unit(); + SVector3 vec3 = SVector3(V[(2+iP)%4]->x()-apex->x(),V[(2+iP)%4]->y()-apex->y(),V[(2+iP)%4]->z()-apex->z()).unit(); + SVector3 crossVec1Vec2 = crossprod(vec1, vec2); + double angle = fabs(acos(dot(crossVec1Vec2, vec3))*180/M_PI); + double minAngle = 30; + if (fabs(angle-90) < minAngle) return false; + } + } + } + return true; +} ////A face with 4 nodes on the boundary should be close to planar ////A face with 3 nodes on the boundary should not exist //bool validFace(MVertex *a, MVertex *b, MVertex *c, MVertex *d, std::map<MVertex*,std::set<MElement*> > &vertexToElements){ @@ -4902,7 +4926,13 @@ void PostOp::execute(GRegion* gr,int level, int conformity){ estimate2 = 0; iterations = 0; + + nbFAILVERTEX=0; + nbFAILVALIDITY=0; + + build_tuples(gr); + if (level >= 2){ init_markings(gr); build_vertex_to_tetrahedra(gr); @@ -4910,19 +4940,31 @@ void PostOp::execute(GRegion* gr,int level, int conformity){ rearrange(gr); } - if (conformity == 1){ + printf("nb FAILS VERTEX after pyramids1 %i\n",nbFAILVERTEX); + printf("nb FAILS VALIDITY after pyramids1 %i\n",nbFAILVALIDITY); + nbFAILVERTEX=0; + nbFAILVALIDITY=0; + + if(conformity == 2 || level >= 3){ init_markings(gr); build_vertex_to_tetrahedra(gr); build_vertex_to_pyramids(gr); - trihedra(gr); + pyramids2(gr); rearrange(gr); - } else if(conformity == 2){ + } + + + printf("nb FAILS VERTEX after pyramids2 %i\n",nbFAILVERTEX); + printf("nb FAILS VALIDITY after pyramids2 %i\n",nbFAILVALIDITY); + + + if (conformity == 1){ init_markings(gr); build_vertex_to_tetrahedra(gr); build_vertex_to_pyramids(gr); - pyramids2(gr); + trihedra(gr); rearrange(gr); - } + } statistics(gr); @@ -5016,7 +5058,7 @@ void PostOp::pyramids1(GRegion* gr){ } -void PostOp::pyramids2(GRegion* gr){ +void PostOp::pyramids2(GRegion* gr, bool allowNonConforming){ unsigned int i; MVertex *a,*b,*c,*d; MVertex *e,*f,*g,*h; @@ -5052,12 +5094,12 @@ void PostOp::pyramids2(GRegion* gr){ g = element->getVertex(6); h = element->getVertex(7); - pyramids2(a,b,c,d,gr); - pyramids2(e,f,g,h,gr); - pyramids2(a,b,f,e,gr); - pyramids2(b,c,g,f,gr); - pyramids2(d,c,g,h,gr); - pyramids2(d,a,e,h,gr); + pyramids2(b,a,d,c,gr, allowNonConforming); + pyramids2(e,f,g,h,gr, allowNonConforming); + pyramids2(a,b,f,e,gr, allowNonConforming); + pyramids2(b,c,g,f,gr, allowNonConforming); + pyramids2(c,d,h,g,gr, allowNonConforming); + pyramids2(d,a,e,h,gr, allowNonConforming); } for(i=0;i<prisms.size();i++){ @@ -5070,9 +5112,9 @@ void PostOp::pyramids2(GRegion* gr){ e = element->getVertex(4); f = element->getVertex(5); - pyramids2(a,d,f,c,gr); - pyramids2(a,b,e,d,gr); - pyramids2(b,c,f,e,gr); + pyramids2(a,d,f,c,gr, allowNonConforming); + pyramids2(a,b,e,d,gr, allowNonConforming); + pyramids2(b,c,f,e,gr, allowNonConforming); } opt1.clear(); @@ -5113,7 +5155,7 @@ void PostOp::pyramids1(MVertex* a,MVertex* b,MVertex* c,MVertex* d,GRegion* gr){ std::map<MElement*,bool>::iterator it1; std::map<MElement*,bool>::iterator it2; - bin1a.clear(); + bin1a.clear(); bin1b.clear(); bin2a.clear(); bin2b.clear(); @@ -5150,11 +5192,15 @@ void PostOp::pyramids1(MVertex* a,MVertex* b,MVertex* c,MVertex* d,GRegion* gr){ if(it1->second==0 && it2->second==0){ vertex = find(a,b,c,d,*it); MVertex* vertex1 = find(a,b,c,d,*bin.begin()); - if(vertex!=0 && vertex == vertex1){//Seb added this 2nd condition. Is it necessary?? - gr->addPyramid(new MPyramid(a,d,c,b,vertex)); - it1->second = 1; - it2->second = 1; - } + if (!vertex || !vertex1) Msg::Fatal("Topological error"); + if(vertex == vertex1){ + MPyramid *pyr = new MPyramid(a,b,c,d,vertex); + if (valid(pyr)){ + gr->addPyramid(pyr); + it1->second = 1; + it2->second = 1; + }else nbFAILVALIDITY++; + }else nbFAILVERTEX++; } } } @@ -5196,11 +5242,11 @@ void PostOp::trihedra(GRegion* gr){ g = element->getVertex(6); h = element->getVertex(7); - trihedra(a,b,c,d,gr); + trihedra(b,a,d,c,gr); trihedra(e,f,g,h,gr); trihedra(a,b,f,e,gr); trihedra(b,c,g,f,gr); - trihedra(d,c,g,h,gr); + trihedra(c,d,h,g,gr); trihedra(d,a,e,h,gr); } @@ -5235,32 +5281,34 @@ void PostOp::trihedra(MVertex* a,MVertex* b,MVertex* c,MVertex* d,GRegion* gr){ find_pyramids_from_tri(a,c,d,diag1b); find_pyramids_from_tri(b,c,d,diag2a); find_pyramids_from_tri(a,b,d,diag2b); - if(diag1a.size()==1 && diag1b.size()==1){ + if(diag1a.size()==1 || diag1b.size()==1){ MTrihedron *trih = new MTrihedron(b, c, d, a); - // if (diag1a.size() != 1 || diag1b.size() != 1) Msg::Error("Quad face neighbor with %i+%i triangular faces (other diagonal: %i+%i) Trihedron: %i",diag1a.size(),diag1b.size(),diag2a.size(),diag2b.size(),trih->getNum()); + if (diag1a.size() != 1 || diag1b.size() != 1 || diag2a.size() != 0 || diag2b.size() != 0) Msg::Error("Quad face neighbor with %i+%i triangular faces (other diagonal: %i+%i) Trihedron: %i",diag1a.size(),diag1b.size(),diag2a.size(),diag2b.size(),trih->getNum()); gr->addTrihedron(trih); - }else if(diag2a.size()==1 && diag2b.size()==1){ + }else if(diag2a.size()==1 || diag2b.size()==1){ MTrihedron *trih = new MTrihedron(a, b, c, d); - // if (diag2a.size() != 1 || diag2b.size() != 1) Msg::Error("Quad face neighbor with %i+%i triangular faces (other diagonal: %i+%i) Trihedron: %i",diag2a.size(),diag2b.size(),diag1a.size(),diag1b.size(),trih->getNum()); + if (diag1a.size() != 0 || diag1b.size() != 0 || diag2a.size() != 1 || diag2b.size() != 1) Msg::Error("Quad face neighbor with %i+%i triangular faces (other diagonal: %i+%i) Trihedron: %i",diag2a.size(),diag2b.size(),diag1a.size(),diag1b.size(),trih->getNum()); gr->addTrihedron(trih); } } -void PostOp::pyramids2(MVertex* a,MVertex* b,MVertex* c,MVertex* d,GRegion* gr){ +void PostOp::pyramids2(MVertex* a,MVertex* b,MVertex* c,MVertex* d,GRegion* gr, bool allowNonConforming){ + + bool flag; double x,y,z; MVertex* mid; - MVertex *diagA,*diagB; + MVertex *diagA,*diagB, *nDiagA, *nDiagB; MVertex *N1,*N2; MVertex *v1,*v2,*v3,*v4,*v5; MTetrahedron* temp; MPyramid* temp2; std::vector<MElement*> movables; std::set<MVertex*> Ns; - std::set<MElement*> bin1; - std::set<MElement*> bin2; - std::set<MElement*> bin3; - std::set<MElement*> bin4; + std::set<MElement*> bin1a, bin1b; + std::set<MElement*> bin2a, bin2b; + std::set<MElement*> bin3a, bin3b; + std::set<MElement*> bin4a, bin4b; std::set<MElement*> tetrahedra; std::set<MElement*> pyramids; std::set<MElement*>::iterator it; @@ -5268,166 +5316,282 @@ void PostOp::pyramids2(MVertex* a,MVertex* b,MVertex* c,MVertex* d,GRegion* gr){ flag = 0; - bin1.clear(); - bin2.clear(); - find_tetrahedra(a,c,bin1); - find_tetrahedra(b,d,bin2); - if(bin1.size()!=0) flag = 1; + bin1a.clear(); + bin1b.clear(); + bin2a.clear(); + bin2b.clear(); + find_tetrahedra(a,c,d,bin1a); + find_tetrahedra(a,b,c,bin1b); + find_tetrahedra(b,d,a,bin2a); + find_tetrahedra(b,c,d,bin2b); - bin3.clear(); - bin4.clear(); - find_pyramids(a,c,bin3); - find_pyramids(b,d,bin4); - if(bin3.size()!=0) flag = 1; + bin3a.clear(); + bin3b.clear(); + bin4a.clear(); + bin4b.clear(); + find_pyramids_from_tri(a,c,d,bin3a); + find_pyramids_from_tri(a,b,c,bin3b); + find_pyramids_from_tri(b,d,a,bin4a); + find_pyramids_from_tri(b,c,d,bin4b); tetrahedra.clear(); - for(it=bin1.begin();it!=bin1.end();it++){ - tetrahedra.insert(*it); - } - for(it=bin2.begin();it!=bin2.end();it++){ - tetrahedra.insert(*it); - } - pyramids.clear(); - for(it=bin3.begin();it!=bin3.end();it++){ - pyramids.insert(*it); - } - for(it=bin4.begin();it!=bin4.end();it++){ - pyramids.insert(*it); + if ((bin1a.size() + bin3a.size() == 1) && (bin1b.size() + bin3b.size() ==1)){ + flag=true; + for(it=bin1a.begin();it!=bin1a.end();it++){ + tetrahedra.insert(*it); + } + for(it=bin1b.begin();it!=bin1b.end();it++){ + tetrahedra.insert(*it); + } + for(it=bin3a.begin();it!=bin3a.end();it++){ + pyramids.insert(*it); + } + for(it=bin3b.begin();it!=bin3b.end();it++){ + pyramids.insert(*it); + } + }else if ((bin2a.size() + bin4a.size() ==1) && (bin2b.size() + bin4b.size() ==1)){ + for(it=bin2a.begin();it!=bin2a.end();it++){ + tetrahedra.insert(*it); + } + for(it=bin2b.begin();it!=bin2b.end();it++){ + tetrahedra.insert(*it); + } + for(it=bin4a.begin();it!=bin4a.end();it++){ + pyramids.insert(*it); + } + for(it=bin4b.begin();it!=bin4b.end();it++){ + pyramids.insert(*it); + } } - /*if(pyramids.size()==0 && tetrahedra.size()==1){ - printf("tetrahedron deleted\n"); - it2 = markings.find(*tetrahedra.begin()); - it2->second = 1; - return; - }*/ if(flag){ - diagA = a; - diagB = c; + diagA = c; + diagB = a; + nDiagA = b; + nDiagB = d; } else{ diagA = b; diagB = d; + nDiagA = c; + nDiagB = a; } Ns.clear(); Ns.insert(diagA); Ns.insert(diagB); - x = (diagA->x() + diagB->x())/2.0; - y = (diagA->y() + diagB->y())/2.0; - z = (diagA->z() + diagB->z())/2.0; + // x = (diagA->x() + diagB->x())/2.0; + // y = (diagA->y() + diagB->y())/2.0; + // z = (diagA->z() + diagB->z())/2.0; mid = 0; movables.clear(); - if(tetrahedra.size()>0 || pyramids.size()>0){ - estimate1 = estimate1 + tetrahedra.size() + 2*pyramids.size(); - estimate2 = estimate2 + 1; - - mid = new MVertex(x,y,z,gr); - gr->addMeshVertex(mid); - - temp2 = new MPyramid(a,b,c,d,mid); - - gr->addPyramid(temp2); - markings.insert(std::pair<MElement*,bool>(temp2,false)); - build_vertex_to_pyramids(temp2); + if(tetrahedra.size()>0 || pyramids.size()>0){ + //A quad face can share only one of those: + // 2 triangles split by the first diagonal + // 2 triangles split by the second diagonal + // 0 triangle with all nodes being on the boundary + if ((bin1a.size()+bin3a.size()) == 1 && (bin1b.size()+bin3b.size()) == 1){ + // MTrihedron *trih = new MTrihedron(b, c, d, a); + // gr->addTrihedron(trih); + }else if ((bin2a.size()+bin4a.size()) == 1 && (bin2b.size()+bin4b.size()) == 1){ + // MTrihedron *trih = new MTrihedron(a, b, c, d); + // gr->addTrihedron(trih); + } + else if (bin1a.size() != 0 || bin1b.size() != 0 || bin2a.size() != 0 || bin2b.size() != 0 + || bin3a.size() != 0 || bin3b.size() != 0 || bin4a.size() != 0 || bin4b.size() != 0 + || a->onWhat()->dim()> 2 || b->onWhat()->dim()> 2 || c->onWhat()->dim()> 2 || d->onWhat()->dim()> 2) + Msg::Fatal("Topological issue: inner quad face facing something else than 2 triangles: %i %i %i %i %i %i %i %i dim %i %i %i",bin1a.size(), bin1b.size(), bin2a.size(), bin2b.size(), bin3a.size(), bin3b.size(), bin4a.size(), bin4b.size(), a->onWhat()->dim(), b->onWhat()->dim(), c->onWhat()->dim(), d->onWhat()->dim()); + + + MVertex* otherV[2]; + int i=0; for(it=tetrahedra.begin();it!=tetrahedra.end();it++){ - N1 = other(*it,diagA,diagB); - N2 = other(*it,diagA,diagB,N1); - - if(N1!=0 && N2!=0){ - Ns.insert(N1); - Ns.insert(N2); - - temp = new MTetrahedron(N1,N2,diagA,mid); - gr->addTetrahedron(temp); - markings.insert(std::pair<MElement*,bool>(temp,false)); - build_vertex_to_tetrahedra(temp); - movables.push_back(temp); - - temp = new MTetrahedron(N1,N2,diagB,mid); - gr->addTetrahedron(temp); - markings.insert(std::pair<MElement*,bool>(temp,false)); - build_vertex_to_tetrahedra(temp); - movables.push_back(temp); - - it2 = markings.find(*it); - it2->second = 1; - erase_vertex_to_tetrahedra(*it); - } + otherV[i++] = findInTriFace(diagA,diagB,nDiagA,nDiagB,*it); } - for(it=pyramids.begin();it!=pyramids.end();it++){ - v1 = (*it)->getVertex(0); - v2 = (*it)->getVertex(1); - v3 = (*it)->getVertex(2); - v4 = (*it)->getVertex(3); - v5 = (*it)->getVertex(4); - - if(v1!=diagA && v1!=diagB){ - Ns.insert(v1); - } - if(v2!=diagA && v2!=diagB){ - Ns.insert(v2); - } - if(v3!=diagA && v3!=diagB){ - Ns.insert(v3); - } - if(v4!=diagA && v4!=diagB){ - Ns.insert(v4); - } - if(v5!=diagA && v5!=diagB){ - Ns.insert(v5); - } + otherV[i++] = findInTriFace(diagA,diagB,nDiagA,nDiagB,*it); + } + if (!otherV[0] || !otherV[1]) Msg::Fatal("Topological error"); + + MPyramid *pyr = new MPyramid(a,b,c,d,otherV[0]); - temp2 = new MPyramid(v1,v2,v3,v4,mid); + if (otherV[0] != otherV[1])nbFAILVERTEX++; + else if (!valid(pyr)) nbFAILVALIDITY++; + + if (otherV[0] == otherV[1] && valid(pyr)){ + estimate1 = estimate1 + tetrahedra.size() + 2*pyramids.size(); + estimate2 = estimate2 + 1; + + //x = (diagA->x() + diagB->x() + otherV[0]->x())/3; + //y = (diagA->y() + diagB->y() + otherV[0]->y())/3; + //z = (diagA->z() + diagB->z() + otherV[0]->z())/3; + + //W create a flat pyramid and let the optimizer fix it + x = (diagA->x() + diagB->x())/2; + y = (diagA->y() + diagB->y())/2; + z = (diagA->z() + diagB->z())/2; + + mid = new MVertex(x,y,z,gr); + gr->addMeshVertex(mid); + + temp2 = new MPyramid(a,b,c,d,mid); + gr->addPyramid(temp2); markings.insert(std::pair<MElement*,bool>(temp2,false)); build_vertex_to_pyramids(temp2); - - if(different(v1,v2,diagA,diagB)){ - temp = new MTetrahedron(v1,v2,mid,v5); - gr->addTetrahedron(temp); - markings.insert(std::pair<MElement*,bool>(temp,false)); - build_vertex_to_tetrahedra(temp); - movables.push_back(temp); - } - - if(different(v2,v3,diagA,diagB)){ - temp = new MTetrahedron(v2,v3,mid,v5); - gr->addTetrahedron(temp); - markings.insert(std::pair<MElement*,bool>(temp,false)); - build_vertex_to_tetrahedra(temp); - movables.push_back(temp); - } - - if(different(v3,v4,diagA,diagB)){ - temp = new MTetrahedron(v3,v4,mid,v5); - gr->addTetrahedron(temp); - markings.insert(std::pair<MElement*,bool>(temp,false)); - build_vertex_to_tetrahedra(temp); - movables.push_back(temp); + // printf("Creating pyramid with vertices %i %i %i %i %i\n", a->getNum(), b->getNum(), c->getNum(), d->getNum(), mid->getNum()); + + + for(it=tetrahedra.begin();it!=tetrahedra.end();it++){ + + MVertex *Nout = findInTriFace(diagA,diagB,nDiagA,nDiagB,*it); + MVertex *Nin = other(*it,diagA,diagB,Nout); + // N1 = other(*it,diagA,diagB); + + + if(Nout!=0 && Nin!=0){ + Ns.insert(N1); + Ns.insert(N2); + + + temp = new MTetrahedron(mid,diagB,Nin,Nout); + gr->addTetrahedron(temp); + markings.insert(std::pair<MElement*,bool>(temp,false)); + build_vertex_to_tetrahedra(temp); + movables.push_back(temp); + // printf("Creating tet with vertices %i %i %i %i\n", N1->getNum(), N2->getNum(), diagA->getNum(), mid->getNum()); + + temp = new MTetrahedron(diagA,mid,Nin,Nout); + gr->addTetrahedron(temp); + markings.insert(std::pair<MElement*,bool>(temp,false)); + build_vertex_to_tetrahedra(temp); + movables.push_back(temp); + // printf("Creating tet with vertices %i %i %i %i\n", N1->getNum(), N2->getNum(), diagB->getNum(), mid->getNum()); + + it2 = markings.find(*it); + it2->second = 1; + erase_vertex_to_tetrahedra(*it); + }else{ + Msg::Fatal("Wrong tetrahedron"); + } } - - if(different(v4,v1,diagA,diagB)){ - temp = new MTetrahedron(v4,v1,mid,v5); - gr->addTetrahedron(temp); - markings.insert(std::pair<MElement*,bool>(temp,false)); - build_vertex_to_tetrahedra(temp); - movables.push_back(temp); + + for(it=pyramids.begin();it!=pyramids.end();it++){ + v1 = (*it)->getVertex(0); + v2 = (*it)->getVertex(1); + v3 = (*it)->getVertex(2); + v4 = (*it)->getVertex(3); + v5 = (*it)->getVertex(4); //apex + + + + //My version (sign-preserving) + temp2 = new MPyramid(v1,v2,v3,v4,mid); + gr->addPyramid(temp2); + markings.insert(std::pair<MElement*,bool>(temp2,false)); + build_vertex_to_pyramids(temp2); + + MVertex *NoutDiag = findInTriFace(diagA, diagB, nDiagA, nDiagB,*it); + MVertex *NoutNDiag = NULL; + for (int iV=0; iV<5; iV++){ + MVertex *v = (*it)->getVertex(iV); + if (v!=a && v!=b && v!=c && v!=d && v!= NoutDiag){ + NoutNDiag = v; + break; + } + } + MVertex *NinNDiag = findInTriFace(diagA, diagB, NoutDiag, NoutNDiag, *it); + if (v5 == diagA){ + temp = new MTetrahedron(diagA, mid, NinNDiag, NoutNDiag); + gr->addTetrahedron(temp); + markings.insert(std::pair<MElement*,bool>(temp,false)); + build_vertex_to_tetrahedra(temp); + movables.push_back(temp); + temp = new MTetrahedron(diagA, mid, NoutNDiag, NoutDiag); + gr->addTetrahedron(temp); + markings.insert(std::pair<MElement*,bool>(temp,false)); + build_vertex_to_tetrahedra(temp); + movables.push_back(temp); + }else if (v5 == diagB){ + temp = new MTetrahedron(mid, diagB, NinNDiag, NoutNDiag); + gr->addTetrahedron(temp); + markings.insert(std::pair<MElement*,bool>(temp,false)); + build_vertex_to_tetrahedra(temp); + movables.push_back(temp); + temp = new MTetrahedron(diagB, mid, NoutNDiag, NoutDiag); + gr->addTetrahedron(temp); + markings.insert(std::pair<MElement*,bool>(temp,false)); + build_vertex_to_tetrahedra(temp); + movables.push_back(temp); + } + + +// if(v1!=diagA && v1!=diagB){ +// Ns.insert(v1); +// } +// if(v2!=diagA && v2!=diagB){ +// Ns.insert(v2); +// } +// if(v3!=diagA && v3!=diagB){ +// Ns.insert(v3); +// } +// if(v4!=diagA && v4!=diagB){ +// Ns.insert(v4); +// } +// if(v5!=diagA && v5!=diagB){ +// Ns.insert(v5); +// } +// +// temp2 = new MPyramid(v1,v2,v3,v4,mid); +// gr->addPyramid(temp2); +// markings.insert(std::pair<MElement*,bool>(temp2,false)); +// build_vertex_to_pyramids(temp2); +// +// if(different(v1,v2,diagA,diagB)){ +// temp = new MTetrahedron(v1,v2,mid,v5); +// gr->addTetrahedron(temp); +// markings.insert(std::pair<MElement*,bool>(temp,false)); +// build_vertex_to_tetrahedra(temp); +// movables.push_back(temp); +// } +// +// if(different(v2,v3,diagA,diagB)){ +// temp = new MTetrahedron(v2,v3,mid,v5); +// gr->addTetrahedron(temp); +// markings.insert(std::pair<MElement*,bool>(temp,false)); +// build_vertex_to_tetrahedra(temp); +// movables.push_back(temp); +// } +// +// if(different(v3,v4,diagA,diagB)){ +// temp = new MTetrahedron(v3,v4,mid,v5); +// gr->addTetrahedron(temp); +// markings.insert(std::pair<MElement*,bool>(temp,false)); +// build_vertex_to_tetrahedra(temp); +// movables.push_back(temp); +// } +// +// if(different(v4,v1,diagA,diagB)){ +// temp = new MTetrahedron(v4,v1,mid,v5); +// gr->addTetrahedron(temp); +// markings.insert(std::pair<MElement*,bool>(temp,false)); +// build_vertex_to_tetrahedra(temp); +// movables.push_back(temp); +// } + + it2 = markings.find(*it); + it2->second = 1; + erase_vertex_to_pyramids(*it); } - - it2 = markings.find(*it); - it2->second = 1; - erase_vertex_to_pyramids(*it); + + // mean(Ns,mid,movables); } - - mean(Ns,mid,movables); } } @@ -5868,6 +6032,24 @@ double PostOp::workaround(MElement* element){ return volume; } +//For an element find a vertex which is in a face inluding in but not out +MVertex* PostOp::findInTriFace(MVertex* in0,MVertex* in1,MVertex* out0,MVertex* out1,MElement* element){ + for(int iF=0;iF<element->getNumFaces();iF++){ + const MFace &face = element->getFace(iF); + if (face.getNumVertices() != 3) continue; + int nbIn = 0; + int hasOut = false; + for (int iV = 0; iV < 3; iV++){ + if (face.getVertex(iV) == in0 || face.getVertex(iV) == in1) nbIn++; + if (face.getVertex(iV) == out0 || face.getVertex(iV) == out1){ hasOut = true; continue;} + } + if (nbIn == 2 && !hasOut) + for (int iV = 0; iV < 3; iV++) + if (face.getVertex(iV) != in0 && face.getVertex(iV) != in1) return face.getVertex(iV); + } + return NULL; +} + MVertex* PostOp::find(MVertex* v1,MVertex* v2,MVertex* v3,MVertex* v4,MElement* element){ int i; MVertex* vertex; diff --git a/Mesh/yamakawa.h b/Mesh/yamakawa.h index 292166beb38bbe68abea16732f6d9b57b29fb74b..6e69f752d10884f8ebbe3710e26186fa29692d54 100644 --- a/Mesh/yamakawa.h +++ b/Mesh/yamakawa.h @@ -619,13 +619,16 @@ private: std::map<MVertex*,std::set<MElement*> > vertex_to_pyramids; std::multiset<Tuple> tuples; std::set<MElement*> triangles; + + int nbFAILVERTEX; + int nbFAILVALIDITY; public: PostOp(); ~PostOp(); void execute(int, int); - //level: 0,1=no pyramid 2=pyramids - //conformity= 0=nonconforming, 1=conformity using trihedra, 2=conformity using pyramids + //level: 0: hex, 1: hex+prisms, 2: hex+prism+1-step pyramids, 3: hex+prism+2-steps pyramids + //conformity= 0=nonconforming, 1=conformity using trihedra void execute(GRegion*,int level, int conformity); inline int get_nb_hexahedra()const{return nbr8;}; @@ -635,10 +638,10 @@ public: void init_markings(GRegion*); void pyramids1(GRegion*); - void pyramids2(GRegion*); + void pyramids2(GRegion*, bool allowNonConforming=false); void trihedra(GRegion*); void pyramids1(MVertex*,MVertex*,MVertex*,MVertex*,GRegion*); - void pyramids2(MVertex*,MVertex*,MVertex*,MVertex*,GRegion*); + void pyramids2(MVertex*,MVertex*,MVertex*,MVertex*,GRegion*, bool allowNonConforming); void trihedra(MVertex*,MVertex*,MVertex*,MVertex*,GRegion*); void rearrange(GRegion*); void statistics(GRegion*); @@ -646,6 +649,9 @@ public: void modify_surfaces(GRegion*); void modify_surfaces(MVertex*,MVertex*,MVertex*,MVertex*); + //returns the geometrical validity of the pyramid + bool valid(MPyramid *pyr); + bool four(MElement*); bool fourTrih(MElement*); bool five(MElement*); @@ -660,6 +666,7 @@ public: double workaround(MElement*); MVertex* find(MVertex*,MVertex*,MVertex*,MVertex*,MElement*); + MVertex* findInTriFace(MVertex* in0,MVertex* in1,MVertex* out0,MVertex* out1,MElement* element); void find_tetrahedra(MVertex*,MVertex*,std::set<MElement*>&); void find_tetrahedra(MVertex*,MVertex*,MVertex*,std::set<MElement*>&); void find_pyramids_from_tri(MVertex*,MVertex*,MVertex*,std::set<MElement*>&);