diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d6dea1190e761a0e574c38cbdee31b1925dfe3a..77e170bfb55a8a8398b127ab300665a659c00453 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,10 +96,9 @@ set(GMSH_API Geo/SVector3.h Geo/STensor3.h Geo/SBoundingBox3d.h Geo/Pair.h Geo/Range.h Geo/SOrientedBoundingBox.h Geo/CellComplex.h Geo/ChainComplex.h Geo/Cell.h Geo/Homology.h Geo/Chain.h Geo/partitionEdge.h Geo/CGNSOptions.h Geo/gmshLevelset.h - Mesh/meshGEdge.h Mesh/meshGFace.h Mesh/meshGFaceOptimize.h - Mesh/meshGFaceElliptic.h Mesh/meshPartition.h - Mesh/meshGFaceDelaunayInsertion.h Mesh/simple3D.h Mesh/meshPartitionOptions.h - Mesh/directions3D.h Mesh/Voronoi3D.h Mesh/Levy3D.h Mesh/periodical.h + Mesh/meshGEdge.h Mesh/meshGFace.h Mesh/meshGFaceOptimize.h Mesh/meshGFaceElliptic.h Mesh/meshPartition.h + Mesh/meshGFaceDelaunayInsertion.h Mesh/simple3D.h Mesh/meshPartitionOptions.h Mesh/directions3D.h Mesh/yamakawa.h + Mesh/Voronoi3D.h Mesh/Levy3D.h Mesh/periodical.h Numeric/mathEvaluator.h Solver/dofManager.h Solver/femTerm.h Solver/laplaceTerm.h Solver/elasticityTerm.h Solver/crossConfTerm.h Solver/orthogonalTerm.h diff --git a/Mesh/CMakeLists.txt b/Mesh/CMakeLists.txt index d216d4f2dbed417d322117b70c9d6e3a2c7af768..b3b4f6640cebf72c8a698aa572c50d6c630adae8 100644 --- a/Mesh/CMakeLists.txt +++ b/Mesh/CMakeLists.txt @@ -35,7 +35,8 @@ set(SRC Levy3D.cpp periodical.cpp directions3D.cpp - Field.cpp + yamakawa.cpp + Field.cpp CenterlineField.cpp ) diff --git a/Mesh/Voronoi3D.h b/Mesh/Voronoi3D.h index 861935ebc5a3fa0c2ff189c71d7f5ead41bf6d2d..8c2fe7941fea4b939a6aa25cf882f29011da6de5 100644 --- a/Mesh/Voronoi3D.h +++ b/Mesh/Voronoi3D.h @@ -2,6 +2,9 @@ // // See the LICENSE.txt file for license information. Please report all // bugs and problems to <gmsh@geuz.org>. +// +// Contributor(s): +// Tristan Carrier #include "GRegion.h" diff --git a/Mesh/directions3D.cpp b/Mesh/directions3D.cpp index 724466562d826a96c8da83b1f367d6da4c520f63..f739a3d386fa1ea98ed4c67f8b4ae86d731b6fb5 100644 --- a/Mesh/directions3D.cpp +++ b/Mesh/directions3D.cpp @@ -2,6 +2,9 @@ // // See the LICENSE.txt file for license information. Please report all // bugs and problems to <gmsh@geuz.org>. +// +// Contributor(s): +// Tristan Carrier #include "directions3D.h" #include "GModel.h" diff --git a/Mesh/directions3D.h b/Mesh/directions3D.h index 317724ab7490b3dcac0d2ad67fca2377dce5a0fe..9dee86a7aa83e0d84d5cad692158f39993784040 100644 --- a/Mesh/directions3D.h +++ b/Mesh/directions3D.h @@ -2,6 +2,9 @@ // // See the LICENSE.txt file for license information. Please report all // bugs and problems to <gmsh@geuz.org>. +// +// Contributor(s): +// Tristan Carrier #include "GFace.h" #include "MElementOctree.h" diff --git a/Mesh/meshGFaceLloyd.h b/Mesh/meshGFaceLloyd.h index 546d7ed438147c1c5ff440f21ee8d26fb8c1662c..9caf0160423eeb7128da10c5721e3c973ff5eeb5 100644 --- a/Mesh/meshGFaceLloyd.h +++ b/Mesh/meshGFaceLloyd.h @@ -2,6 +2,9 @@ // // See the LICENSE.txt file for license information. Please report all // bugs and problems to <gmsh@geuz.org>. +// +// Contributor(s): +// Tristan Carrier #ifndef _MESH_GFACE_LLOYD_H_ #define _MESH_GFACE_LLOYD_H_ diff --git a/Mesh/periodical.h b/Mesh/periodical.h index 2a167342d5703ad1bbad110f898c7e45e0ec86a5..3cc0a76bb79c03021ee9a8f2dde628ed5e0476a3 100644 --- a/Mesh/periodical.h +++ b/Mesh/periodical.h @@ -2,6 +2,9 @@ // // See the LICENSE.txt file for license information. Please report all // bugs and problems to <gmsh@geuz.org>. +// +// Contributor(s): +// Tristan Carrier #include "GRegion.h" diff --git a/Mesh/simple3D.cpp b/Mesh/simple3D.cpp index 80d2a4e3d82a9b5e4442f3ed7621aa0bb0a945ed..0d652dbb3f3859d33b5b5510f2a67294837d41e7 100644 --- a/Mesh/simple3D.cpp +++ b/Mesh/simple3D.cpp @@ -2,6 +2,9 @@ // // See the LICENSE.txt file for license information. Please report all // bugs and problems to <gmsh@geuz.org>. +// +// Contributor(s): +// Tristan Carrier #include "simple3D.h" #include "GModel.h" diff --git a/Mesh/simple3D.h b/Mesh/simple3D.h index 1086e518694d204af67c83516c716ac63bf0c6c9..9c81c32ff002e18ed49f01570d9be2131ab71e77 100644 --- a/Mesh/simple3D.h +++ b/Mesh/simple3D.h @@ -2,6 +2,9 @@ // // See the LICENSE.txt file for license information. Please report all // bugs and problems to <gmsh@geuz.org>. +// +// Contributor(s): +// Tristan Carrier #include "SVector3.h" #include <list> diff --git a/Mesh/yamakawa.cpp b/Mesh/yamakawa.cpp new file mode 100755 index 0000000000000000000000000000000000000000..9bed0d58dd867b755caedc110f85a97d04f9b244 --- /dev/null +++ b/Mesh/yamakawa.cpp @@ -0,0 +1,1228 @@ +// Gmsh - Copyright (C) 1997-2011 C. Geuzaine, J.-F. Remacle +// +// See the LICENSE.txt file for license information. Please report all +// bugs and problems to <gmsh@geuz.org>. +// +// Contributor(s): +// Tristan Carrier + +#include "yamakawa.h" +#include "GModel.h" +#include "MVertex.h" +#include "MElement.h" +#include <fstream> +#include "MHexahedron.h" +#include "MQuadrangle.h" + +/****************class Hex****************/ + +Hex::Hex(){} + +Hex::Hex(MVertex* a2,MVertex* b2,MVertex* c2,MVertex* d2,MVertex* e2,MVertex* f2,MVertex* g2,MVertex* h2){ + a = a2; + b = b2; + c = c2; + d = d2; + e = e2; + f = f2; + g = g2; + h = h2; +} + +Hex::~Hex(){} + +double Hex::get_quality() const{ + return quality; +} + +void Hex::set_quality(double new_quality){ + quality = new_quality; +} + +MVertex* Hex::get_a(){ + return a; +} + +MVertex* Hex::get_b(){ + return b; +} + +MVertex* Hex::get_c(){ + return c; +} + +MVertex* Hex::get_d(){ + return d; +} + +MVertex* Hex::get_e(){ + return e; +} + +MVertex* Hex::get_f(){ + return f; +} + +MVertex* Hex::get_g(){ + return g; +} + +MVertex* Hex::get_h(){ + return h; +} + +void Hex::set_vertices(MVertex* a2,MVertex* b2,MVertex* c2,MVertex* d2,MVertex* e2,MVertex* f2,MVertex* g2,MVertex* h2){ + a = a2; + b = b2; + c = c2; + d = d2; + e = e2; + f = f2; + g = g2; + h = h2; +} + +bool Hex::operator<(const Hex& hex) const{ + return quality>hex.get_quality(); +} + +/****************class Recombinator****************/ + +Recombinator::Recombinator(){} + +Recombinator::~Recombinator(){} + +void Recombinator::execute(){ + GRegion* gr; + GModel* model = GModel::current(); + GModel::riter it; + + for(it=model->firstRegion();it!=model->lastRegion();it++) + { + gr = *it; + if(gr->getNumMeshElements()>0){ + execute(gr); + } + } +} + +void Recombinator::execute(GRegion* gr){ + init_markings(gr); + + build_vertex_to_vertices(gr); + build_vertex_to_elements(gr); + + potential.clear(); + patern1(gr); + patern2(gr); + patern3(gr); + + std::sort(potential.begin(),potential.end()); + + merge(gr); + + rearrange(gr); + + statistics(gr); +} + +void Recombinator::init_markings(GRegion* gr){ + int i; + MElement* element; + + markings.clear(); + + for(i=0;i<gr->getNumMeshElements();i++){ + element = gr->getMeshElement(i); + markings.insert(std::pair<MElement*,bool>(element,0)); + } +} + +void Recombinator::patern1(GRegion* gr){ + int i; + int index; + double quality; + MElement* element; + MVertex *a,*b,*c,*d; + MVertex *p,*q,*r,*s; + std::vector<MVertex*> already1; + std::vector<MVertex*> already2; + std::vector<MVertex*> already3; + std::vector<MVertex*> already4; + std::set<MVertex*> bin1; + std::set<MVertex*> bin2; + std::set<MVertex*> bin3; + std::set<MVertex*> bin4; + std::set<MVertex*>::iterator it1; + std::set<MVertex*>::iterator it2; + std::set<MVertex*>::iterator it3; + std::set<MVertex*>::iterator it4; + Hex hex; + + for(i=0;i<gr->getNumMeshElements();i++){ + element = gr->getMeshElement(i); + max_scaled_jacobian(element,index); + + a = element->getVertex(index); + b = element->getVertex((index+1)%4); + c = element->getVertex((index+2)%4); + d = element->getVertex((index+3)%4); + + already1.clear(); + already1.push_back(a); + already1.push_back(b); + already1.push_back(c); + already1.push_back(d); + bin1.clear(); + find(b,d,already1,bin1); + for(it1=bin1.begin();it1!=bin1.end();it1++){ + p = *it1; + already2.clear(); + already2.push_back(a); + already2.push_back(b); + already2.push_back(c); + already2.push_back(d); + already2.push_back(p); + bin2.clear(); + find(b,c,already2,bin2); + for(it2=bin2.begin();it2!=bin2.end();it2++){ + q = *it2; + already3.clear(); + already3.push_back(a); + already3.push_back(b); + already3.push_back(c); + already3.push_back(d); + already3.push_back(p); + already3.push_back(q); + bin3.clear(); + find(c,d,already3,bin3); + for(it3=bin3.begin();it3!=bin3.end();it3++){ + r = *it3; + already4.clear(); + already4.push_back(a); + already4.push_back(b); + already4.push_back(c); + already4.push_back(d); + already4.push_back(p); + already4.push_back(q); + already4.push_back(r); + bin4.clear(); + find(p,q,r,already4,bin4); + for(it4=bin4.begin();it4!=bin4.end();it4++){ + s = *it4; + hex = Hex(a,b,q,c,d,p,s,r); + quality = min_scaled_jacobian(hex); + hex.set_quality(quality); + if(valid(hex)){ + potential.push_back(hex); + } + } + } + } + } + } +} + +void Recombinator::patern2(GRegion* gr){ + int i; + int index1,index2,index3,index4; + double quality; + MElement* element; + MVertex *a,*b,*c,*d; + MVertex *p,*q,*r,*s; + std::set<MElement*> verif; + Hex hex; + + for(i=0;i<gr->getNumMeshElements();i++){ + element = gr->getMeshElement(i); + diagonal(element,index1,index2); + two_others(index1,index2,index3,index4); + + b = element->getVertex(index1); + d = element->getVertex(index2); + a = element->getVertex(index3); + c = element->getVertex(index4); + + verif.clear(); + find(b,d,verif); + if(verif.size()==6){ + s = find(a,b,d,c,verif); + p = find(b,c,d,a,verif); + if(s!=0 && p!=0){ + r = find(s,b,d,a,verif); + q = find(p,b,d,c,verif); + if(r!=0 && q!=0){ + hex = Hex(a,s,b,c,d,r,q,p); + quality = min_scaled_jacobian(hex); + hex.set_quality(quality); + if(valid(hex)){ + potential.push_back(hex); + } + + hex = Hex(a,c,d,s,b,p,q,r); + quality = min_scaled_jacobian(hex); + hex.set_quality(quality); + if(valid(hex)){ + potential.push_back(hex); + } + } + } + } + } +} + +void Recombinator::patern3(GRegion* gr){ + int i; + int index1,index2,index3,index4; + bool c1,c2,c3,c4,c5; + bool c6,c7,c8,c9,c10; + double quality; + MElement* element; + MVertex *a,*b,*c,*d; + MVertex *p,*q,*r,*s; + MVertex *fA,*fB,*bA,*bB; + std::set<MElement*> verif1; + std::set<MElement*> verif2; + Hex hex; + + for(i=0;i<gr->getNumMeshElements();i++){ + element = gr->getMeshElement(i); + diagonal(element,index1,index2); + two_others(index1,index2,index3,index4); + + b = element->getVertex(index1); + d = element->getVertex(index2); + a = element->getVertex(index3); + c = element->getVertex(index4); + + verif1.clear(); + verif2.clear(); + find(b,d,verif1); + find(a,c,verif2); + + if(verif1.size()==4 && verif2.size()==4){ + fA = find(b,d,a,c,verif1); + fB = find(b,d,c,a,verif1); + bA = find(a,c,b,d,verif2); + bB = find(a,c,d,b,verif2); + + if(fA!=0 && fB!=0 && bA!=0 && bB!=0 && fA!=fB && bA!=bB){ + if(scalar(fA,fB,a,b)>scalar(fA,fB,b,c) && scalar(bA,bB,a,b)>scalar(bA,bB,b,c)){ + if(distance(fA,b,c)<distance(fB,b,c)){ + p = fA; + q = fB; + } + else{ + p = fB; + q = fA; + } + + if(distance(bA,b,c)<distance(bB,b,c)){ + r = bA; + s = bB; + } + else{ + r = bB; + s = bA; + } + + c1 = linked(b,p); + c2 = linked(c,p); + c3 = linked(p,q); + c4 = linked(a,q); + c5 = linked(d,q); + + c6 = linked(b,r); + c7 = linked(c,r); + c8 = linked(r,s); + c9 = linked(a,s); + c10 = linked(d,s); + + if(c1 && c2 && c3 && c4 && c5 && c6 && c7 && c8 && c9 && c10){ + hex = Hex(p,c,r,b,q,d,s,a); + quality = min_scaled_jacobian(hex); + hex.set_quality(quality); + if(valid(hex)){ + potential.push_back(hex); + } + } + } + else if(scalar(fA,fB,a,b)<=scalar(fA,fB,b,c) && scalar(bA,bB,a,b)<=scalar(bA,bB,b,c)){ + if(distance(fA,a,b)<distance(fB,a,b)){ + p = fA; + q = fB; + } + else{ + p = fB; + q = fA; + } + + if(distance(bA,a,b)<distance(bB,a,b)){ + r = bA; + s = bB; + } + else{ + r = bB; + s = bA; + } + + c1 = linked(b,p); + c2 = linked(a,p); + c3 = linked(p,q); + c4 = linked(c,q); + c5 = linked(d,q); + + c6 = linked(b,r); + c7 = linked(a,r); + c8 = linked(r,s); + c9 = linked(c,s); + c10 = linked(d,s); + + if(c1 && c2 && c3 && c4 && c5 && c6 && c7 && c8 && c9 && c10){ + hex = Hex(p,b,r,a,q,c,s,d); + quality = min_scaled_jacobian(hex); + hex.set_quality(quality); + if(valid(hex)){ + potential.push_back(hex); + } + } + } + } + } + } +} + +void Recombinator::merge(GRegion* gr){ + int i; + int count; + bool flag; + double threshold; + double quality; + MVertex *a,*b,*c,*d; + MVertex *e,*f,*g,*h; + MElement* element; + std::set<MElement*> parts; + std::set<MElement*>::iterator it; + std::map<MElement*,bool>::iterator it2; + std::vector<MTetrahedron*>::iterator it3; + Hex hex; + + count = 1; + quality = 0.0; + + for(i=0;i<potential.size();i++){ + hex = potential[i]; + + a = hex.get_a(); + b = hex.get_b(); + c = hex.get_c(); + d = hex.get_d(); + e = hex.get_e(); + f = hex.get_f(); + g = hex.get_g(); + h = hex.get_h(); + + parts.clear(); + find(a,hex,parts); + find(b,hex,parts); + find(c,hex,parts); + find(d,hex,parts); + find(e,hex,parts); + find(f,hex,parts); + find(g,hex,parts); + find(h,hex,parts); + + flag = 1; + + for(it=parts.begin();it!=parts.end();it++){ + element = *it; + it2 = markings.find(element); + if(it2->second==1 && !sliver(element,hex)){ + flag = 0; + break; + } + } + + threshold = 0.25; + if(hex.get_quality()<threshold){ + flag = 0; + } + + if(!valid(hex,parts)){ + flag = 0; + } + + if(flag){ + printf("%d - %d/%d - %f\n",count,i,potential.size(),hex.get_quality()); + quality = quality + hex.get_quality(); + for(it=parts.begin();it!=parts.end();it++){ + element = *it; + it2 = markings.find(element); + it2->second = 1; + } + gr->addHexahedron(new MHexahedron(a,b,c,d,e,f,g,h)); + count++; + } + } + + it3 = gr->tetrahedra.begin(); + while(it3!=gr->tetrahedra.end()){ + element = (MElement*)(*it3); + it2 = markings.find(element); + if(it2->second==1){ + it3 = gr->tetrahedra.erase(it3); + } + else{ + it3++; + } + } + + printf("hex average quality (0->1) : %f\n",quality/count); +} + +void Recombinator::rearrange(GRegion* gr){ + int i; + MElement* element; + + for(i=0;i<gr->getNumMeshElements();i++){ + element = gr->getMeshElement(i); + element->setVolumePositive(); + } +} + +void Recombinator::statistics(GRegion* gr){ + int i; + int all_nbr,hex_nbr; + double all_volume,hex_volume,volume; + MElement* element; + + all_nbr = 0; + hex_nbr = 0; + all_volume = 0.0; + hex_volume = 0.0; + + for(i=0;i<gr->getNumMeshElements();i++){ + element = gr->getMeshElement(i); + volume = element->getVolume(); + + if(element->getNumVertices()==8){ + hex_nbr = hex_nbr + 1; + hex_volume = hex_volume + volume; + } + + all_nbr = all_nbr + 1; + all_volume = all_volume + volume; + } + + printf("percentage of hex (number) : %.2f\n",hex_nbr*100.0/all_nbr); + printf("percentage of hex (volume) : %.2f\n",hex_volume*100.0/all_volume); +} + +bool Recombinator::sliver(MElement* element,Hex hex){ + bool val; + bool flag1,flag2,flag3,flag4; + MVertex *a,*b,*c,*d; + + val = 0; + a = element->getVertex(0); + b = element->getVertex(1); + c = element->getVertex(2); + d = element->getVertex(3); + + flag1 = inclusion(a,hex.get_a(),hex.get_b(),hex.get_c(),hex.get_d()); + flag2 = inclusion(b,hex.get_a(),hex.get_b(),hex.get_c(),hex.get_d()); + flag3 = inclusion(c,hex.get_a(),hex.get_b(),hex.get_c(),hex.get_d()); + flag4 = inclusion(d,hex.get_a(),hex.get_b(),hex.get_c(),hex.get_d()); + if(flag1 && flag2 && flag3 && flag4) val = 1; + + flag1 = inclusion(a,hex.get_e(),hex.get_f(),hex.get_g(),hex.get_h()); + flag2 = inclusion(b,hex.get_e(),hex.get_f(),hex.get_g(),hex.get_h()); + flag3 = inclusion(c,hex.get_e(),hex.get_f(),hex.get_g(),hex.get_h()); + flag4 = inclusion(d,hex.get_e(),hex.get_f(),hex.get_g(),hex.get_h()); + if(flag1 && flag2 && flag3 && flag4) val = 1; + + flag1 = inclusion(a,hex.get_a(),hex.get_b(),hex.get_e(),hex.get_f()); + flag2 = inclusion(b,hex.get_a(),hex.get_b(),hex.get_e(),hex.get_f()); + flag3 = inclusion(c,hex.get_a(),hex.get_b(),hex.get_e(),hex.get_f()); + flag4 = inclusion(d,hex.get_a(),hex.get_b(),hex.get_e(),hex.get_f()); + if(flag1 && flag2 && flag3 && flag4) val = 1; + + flag1 = inclusion(a,hex.get_b(),hex.get_c(),hex.get_g(),hex.get_f()); + flag2 = inclusion(b,hex.get_b(),hex.get_c(),hex.get_g(),hex.get_f()); + flag3 = inclusion(c,hex.get_b(),hex.get_c(),hex.get_g(),hex.get_f()); + flag4 = inclusion(d,hex.get_b(),hex.get_c(),hex.get_g(),hex.get_f()); + if(flag1 && flag2 && flag3 && flag4) val = 1; + + flag1 = inclusion(a,hex.get_c(),hex.get_d(),hex.get_g(),hex.get_h()); + flag2 = inclusion(b,hex.get_c(),hex.get_d(),hex.get_g(),hex.get_h()); + flag3 = inclusion(c,hex.get_c(),hex.get_d(),hex.get_g(),hex.get_h()); + flag4 = inclusion(d,hex.get_c(),hex.get_d(),hex.get_g(),hex.get_h()); + if(flag1 && flag2 && flag3 && flag4) val = 1; + + flag1 = inclusion(a,hex.get_a(),hex.get_d(),hex.get_e(),hex.get_h()); + flag2 = inclusion(b,hex.get_a(),hex.get_d(),hex.get_e(),hex.get_h()); + flag3 = inclusion(c,hex.get_a(),hex.get_d(),hex.get_e(),hex.get_h()); + flag4 = inclusion(d,hex.get_a(),hex.get_d(),hex.get_e(),hex.get_h()); + if(flag1 && flag2 && flag3 && flag4) val = 1; + + return val; +} + +double Recombinator::diagonal(MElement* element,int& index1,int& index2){ + double max; + double l1,l2,l3,l4,l5,l6; + MVertex *a,*b,*c,*d; + + a = element->getVertex(0); + b = element->getVertex(1); + c = element->getVertex(2); + d = element->getVertex(3); + + max = 1000000.0; + l1 = distance(a,b); + l2 = distance(a,c); + l3 = distance(a,d); + l4 = distance(b,c); + l5 = distance(c,d); + l6 = distance(d,b); + + if(l1>=l2 && l1>=l3 && l1>=l4 && l1>=l5 && l1>=l6){ + index1 = 0; + index2 = 1; + max = l1; + } + else if(l2>=l1 && l2>=l3 && l2>=l4 && l2>=l5 && l2>=l6){ + index1 = 0; + index2 = 2; + max = l2; + } + else if(l3>=l1 && l3>=l2 && l3>=l4 && l3>=l5 && l3>=l6){ + index1 = 0; + index2 = 3; + max = l3; + } + else if(l4>=l1 && l4>=l2 && l4>=l3 && l4>=l5 && l4>=l6){ + index1 = 1; + index2 = 2; + max = l4; + } + else if(l5>=l1 && l5>=l2 && l5>=l3 && l5>=l4 && l5>=l6){ + index1 = 2; + index2 = 3; + max = l5; + } + else if(l6>=l1 && l6>=l2 && l6>=l3 && l6>=l4 && l6>=l5){ + index1 = 3; + index2 = 1; + max = l6; + } + + return max; +} + +double Recombinator::distance(MVertex* v1,MVertex* v2){ + double val; + double x,y,z; + + x = v2->x() - v1->x(); + y = v2->y() - v1->y(); + z = v2->z() - v1->z(); + + val = sqrt(x*x + y*y + z*z); + return val; +} + +double Recombinator::distance(MVertex* v,MVertex* v1,MVertex* v2){ + double val; + double x,y,z; + + x = 0.5*(v2->x() + v1->x()) - v->x(); + y = 0.5*(v2->y() + v1->y()) - v->y(); + z = 0.5*(v2->z() + v1->z()) - v->z(); + + val = sqrt(x*x + y*y + z*z); + return val; +} + +double Recombinator::scalar(MVertex* v1,MVertex* v2,MVertex* v3,MVertex* v4){ + double val; + double l1,l2; + SVector3 vec1,vec2; + + vec1 = SVector3(v2->x()-v1->x(),v2->y()-v1->y(),v2->z()-v1->z()); + vec2 = SVector3(v4->x()-v3->x(),v4->y()-v3->y(),v4->z()-v3->z()); + + l1 = vec1.norm(); + l2 = vec2.norm(); + + val = dot(vec1,vec2); + return fabs(val)/(l1*l2); +} + +void Recombinator::two_others(int index1,int index2,int& index3,int& index4){ + int i; + + for(i=0;i<4;i++){ + if(i!=index1 && i!=index2){ + index3 = i; + break; + } + } + + for(i=0;i<4;i++){ + if(i!=index1 && i!=index2 && i!=index3){ + index4 = i; + break; + } + } +} + +bool Recombinator::valid(Hex hex,const std::set<MElement*>& parts){ + bool ok1,ok2,ok3; + bool ok4,ok5,ok6; + bool flag1A,flag1B,flag1C,flag1D; + bool flag2A,flag2B,flag2C,flag2D; + bool flag3A,flag3B,flag3C,flag3D; + bool flag4A,flag4B,flag4C,flag4D; + bool flag5A,flag5B,flag5C,flag5D; + bool flag6A,flag6B,flag6C,flag6D; + MVertex *a,*b,*c,*d; + MVertex *e,*f,*g,*h; + + a = hex.get_a(); + b = hex.get_b(); + c = hex.get_c(); + d = hex.get_d(); + e = hex.get_e(); + f = hex.get_f(); + g = hex.get_g(); + h = hex.get_h(); + + flag1A = inclusion(a,b,c,parts); + flag1B = inclusion(a,c,d,parts); + flag1C = inclusion(b,c,d,parts); + flag1D = inclusion(a,b,d,parts); + ok1 = (flag1A && flag1B) || (flag1C && flag1D); + + flag2A = inclusion(e,f,g,parts); + flag2B = inclusion(e,g,h,parts); + flag2C = inclusion(f,g,h,parts); + flag2D = inclusion(e,f,h,parts); + ok2 = (flag2A && flag2B) || (flag2C && flag2D); + + flag3A = inclusion(a,b,f,parts); + flag3B = inclusion(a,f,e,parts); + flag3C = inclusion(b,e,f,parts); + flag3D = inclusion(a,b,e,parts); + ok3 = (flag3A && flag3B) || (flag3C && flag3D); + + flag4A = inclusion(b,c,g,parts); + flag4B = inclusion(b,g,f,parts); + flag4C = inclusion(c,g,f,parts); + flag4D = inclusion(b,c,f,parts); + ok4 = (flag4A && flag4B) || (flag4C && flag4D); + + flag5A = inclusion(c,d,g,parts); + flag5B = inclusion(d,g,h,parts); + flag5C = inclusion(c,g,h,parts); + flag5D = inclusion(c,d,h,parts); + ok5 = (flag5A && flag5B) || (flag5C && flag5D); + + flag6A = inclusion(a,d,h,parts); + flag6B = inclusion(a,e,h,parts); + flag6C = inclusion(d,e,h,parts); + flag6D = inclusion(a,d,e,parts); + ok6 = (flag6A && flag6B) || (flag6C && flag6D); + + if(ok1 && ok2 && ok3 && ok4 && ok5 && ok6){ + return 1; + } + else{ + return 0; + } +} + +bool Recombinator::valid(Hex hex){ + double k; + double eta1,eta2,eta3; + double eta4,eta5,eta6; + MVertex *a,*b,*c,*d; + MVertex *e,*f,*g,*h; + + k = 0.000001; + + a = hex.get_a(); + b = hex.get_b(); + c = hex.get_c(); + d = hex.get_d(); + e = hex.get_e(); + f = hex.get_f(); + g = hex.get_g(); + h = hex.get_h(); + + eta1 = eta(a,b,c,d); + eta2 = eta(e,f,g,h); + eta3 = eta(a,b,f,e); + eta4 = eta(b,c,g,f); + eta5 = eta(d,a,e,h); + eta6 = eta(d,c,g,h); + + if(eta1>k && eta2>k && eta3>k && eta4>k && eta5>k && eta6>k){ + return 1; + } + else{ + return 0; + } +} + +double Recombinator::eta(MVertex* a,MVertex* b,MVertex* c,MVertex* d){ + double val; + MQuadrangle* quad; + + quad = new MQuadrangle(a,b,c,d); + val = quad->etaShapeMeasure(); + delete quad; + return val; +} + +bool Recombinator::linked(MVertex* v1,MVertex* v2){ + bool flag; + std::map<MVertex*,std::set<MVertex*> >::iterator it; + std::set<MVertex*>::iterator it2; + + it = vertex_to_vertices.find(v1); + flag = 0; + + for(it2=(it->second).begin();it2!=(it->second).end();it2++){ + if(*it2==v2){ + flag = 1; + break; + } + } + + return flag; +} + +void Recombinator::find(MVertex* v1,MVertex* v2,const std::vector<MVertex*>& already,std::set<MVertex*>& final){ + std::map<MVertex*,std::set<MVertex*> >::iterator it1; + std::map<MVertex*,std::set<MVertex*> >::iterator it2; + + it1 = vertex_to_vertices.find(v1); + it2 = vertex_to_vertices.find(v2); + + intersection(it1->second,it2->second,already,final); +} + +void Recombinator::find(MVertex* v1,MVertex* v2,MVertex* v3,const std::vector<MVertex*>& already,std::set<MVertex*>& final){ + std::map<MVertex*,std::set<MVertex*> >::iterator it1; + std::map<MVertex*,std::set<MVertex*> >::iterator it2; + std::map<MVertex*,std::set<MVertex*> >::iterator it3; + + it1 = vertex_to_vertices.find(v1); + it2 = vertex_to_vertices.find(v2); + it3 = vertex_to_vertices.find(v3); + + intersection(it1->second,it2->second,it3->second,already,final); +} + +void Recombinator::find(MVertex* v1,MVertex* v2,std::set<MElement*>& final){ + std::map<MVertex*,std::set<MElement*> >::iterator it1; + std::map<MVertex*,std::set<MElement*> >::iterator it2; + + it1 = vertex_to_elements.find(v1); + it2 = vertex_to_elements.find(v2); + + intersection(it1->second,it2->second,final); +} + +void Recombinator::find(MVertex* vertex,Hex hex,std::set<MElement*>& final){ + bool flag1,flag2,flag3,flag4; + MVertex *a,*b,*c,*d; + std::map<MVertex*,std::set<MElement*> >::iterator it; + std::set<MElement*>::iterator it2; + + it = vertex_to_elements.find(vertex); + + for(it2=(it->second).begin();it2!=(it->second).end();it2++){ + a = (*it2)->getVertex(0); + b = (*it2)->getVertex(1); + c = (*it2)->getVertex(2); + d = (*it2)->getVertex(3); + + flag1 = inclusion(a,hex); + flag2 = inclusion(b,hex); + flag3 = inclusion(c,hex); + flag4 = inclusion(d,hex); + + if(flag1 && flag2 && flag3 && flag4){ + final.insert(*it2); + } + } +} + +MVertex* Recombinator::find(MVertex* v1,MVertex* v2,MVertex* v3,MVertex* already,const std::set<MElement*>& bin){ + bool flag1,flag2,flag3,flag4; + MElement* element; + MVertex *a,*b,*c,*d; + MVertex* pointer; + std::set<MElement*>::iterator it; + + pointer = 0; + + for(it=bin.begin();it!=bin.end();it++){ + element = *it; + + a = element->getVertex(0); + b = element->getVertex(1); + c = element->getVertex(2); + d = element->getVertex(3); + + flag1 = inclusion(v1,a,b,c,d); + flag2 = inclusion(v2,a,b,c,d); + flag3 = inclusion(v3,a,b,c,d); + flag4 = inclusion(already,a,b,c,d); + + if(flag1 && flag2 && flag3 && !flag4){ + if(a!=v1 && a!=v2 && a!=v3){ + pointer = a; + } + else if(b!=v1 && b!=v2 && b!=v3){ + pointer = b; + } + else if(c!=v1 && c!=v2 && c!=v3){ + pointer = c; + } + else{ + pointer = d; + } + break; + } + } + + return pointer; +} + +void Recombinator::intersection(const std::set<MVertex*>& bin1,const std::set<MVertex*>& bin2, + const std::vector<MVertex*>& already,std::set<MVertex*>& final){ + int i; + bool ok; + std::set<MVertex*> temp; + std::set<MVertex*>::iterator it; + + std::set_intersection(bin1.begin(),bin1.end(),bin2.begin(),bin2.end(),std::inserter(temp,temp.end())); + + for(it=temp.begin();it!=temp.end();it++){ + ok = 1; + + for(i=0;i<already.size();i++){ + if((*it)==already[i]){ + ok = 0; + break; + } + } + + if(ok){ + final.insert(*it); + } + } +} + +void Recombinator::intersection(const std::set<MVertex*>& bin1,const std::set<MVertex*>& bin2,const std::set<MVertex*>& bin3, + const std::vector<MVertex*>& already,std::set<MVertex*>& final){ + int i; + bool ok; + std::set<MVertex*> temp; + std::set<MVertex*> temp2; + std::set<MVertex*>::iterator it; + + std::set_intersection(bin1.begin(),bin1.end(),bin2.begin(),bin2.end(),std::inserter(temp,temp.end())); + std::set_intersection(temp.begin(),temp.end(),bin3.begin(),bin3.end(),std::inserter(temp2,temp2.end())); + + for(it=temp2.begin();it!=temp2.end();it++){ + ok = 1; + + for(i=0;i<already.size();i++){ + if((*it)==already[i]){ + ok = 0; + break; + } + } + + if(ok){ + final.insert(*it); + } + } +} + +void Recombinator::intersection(const std::set<MElement*>& bin1,const std::set<MElement*>& bin2,std::set<MElement*>& final){ + std::set_intersection(bin1.begin(),bin1.end(),bin2.begin(),bin2.end(),std::inserter(final,final.end())); +} + +bool Recombinator::inclusion(MVertex* vertex,Hex hex){ + bool flag; + + flag = 0; + + if(vertex==hex.get_a()) flag = 1; + else if(vertex==hex.get_b()) flag = 1; + else if(vertex==hex.get_c()) flag = 1; + else if(vertex==hex.get_d()) flag = 1; + else if(vertex==hex.get_e()) flag = 1; + else if(vertex==hex.get_f()) flag = 1; + else if(vertex==hex.get_g()) flag = 1; + else if(vertex==hex.get_h()) flag = 1; + + return flag; +} + +bool Recombinator::inclusion(MVertex* vertex,MVertex* a,MVertex* b,MVertex* c,MVertex* d){ + bool flag; + + flag = 0; + + if(vertex==a) flag = 1; + else if(vertex==b) flag = 1; + else if(vertex==c) flag = 1; + else if(vertex==d) flag = 1; + + return flag; +} + +bool Recombinator::inclusion(MVertex* v1,MVertex* v2,MVertex* v3,const std::set<MElement*>& bin){ + bool ok; + bool flag1,flag2,flag3; + MVertex *a,*b,*c,*d; + MElement* element; + std::set<MElement*>::iterator it; + + ok = 0; + + for(it=bin.begin();it!=bin.end();it++){ + element = *it; + + a = element->getVertex(0); + b = element->getVertex(1); + c = element->getVertex(2); + d = element->getVertex(3); + + flag1 = inclusion(v1,a,b,c,d); + flag2 = inclusion(v2,a,b,c,d); + flag3 = inclusion(v3,a,b,c,d); + + if(flag1 && flag2 && flag3){ + ok = 1; + break; + } + } + + return ok; +} + +void Recombinator::build_vertex_to_vertices(GRegion* gr){ + int i,j; + MElement* element; + MVertex *a,*b,*c,*d; + std::set<MVertex*> bin; + std::map<MVertex*,std::set<MVertex*> >::iterator it; + + vertex_to_vertices.clear(); + + for(i=0;i<gr->getNumMeshElements();i++){ + element = gr->getMeshElement(i); + for(j=0;j<element->getNumVertices();j++){ + a = element->getVertex(j); + b = element->getVertex((j+1)%4); + c = element->getVertex((j+2)%4); + d = element->getVertex((j+3)%4); + + it = vertex_to_vertices.find(a); + if(it!=vertex_to_vertices.end()){ + it->second.insert(b); + it->second.insert(c); + it->second.insert(d); + } + else{ + bin.clear(); + bin.insert(b); + bin.insert(c); + bin.insert(d); + vertex_to_vertices.insert(std::pair<MVertex*,std::set<MVertex*> >(a,bin)); + } + } + } +} + +void Recombinator::build_vertex_to_elements(GRegion* gr){ + int i,j; + MElement* element; + MVertex* vertex; + std::set<MElement*> bin; + std::map<MVertex*,std::set<MElement*> >::iterator it; + + vertex_to_elements.clear(); + + for(i=0;i<gr->getNumMeshElements();i++){ + element = gr->getMeshElement(i); + for(j=0;j<element->getNumVertices();j++){ + vertex = element->getVertex(j); + + it = vertex_to_elements.find(vertex); + if(it!=vertex_to_elements.end()){ + it->second.insert(element); + } + else{ + bin.clear(); + bin.insert(element); + vertex_to_elements.insert(std::pair<MVertex*,std::set<MElement*> >(vertex,bin)); + } + } + } +} + +void Recombinator::print_vertex_to_vertices(GRegion* gr){ + int i,j; + SPoint3 p1,p2; + MElement* element; + MVertex* vertex; + std::map<MVertex*,std::set<MVertex*> >::iterator it; + std::set<MVertex*>::iterator it2; + + std::ofstream file("vertex_to_vertices.pos"); + file << "View \"test\" {\n"; + + for(i=0;i<gr->getNumMeshElements();i++){ + element = gr->getMeshElement(i); + for(j=0;j<element->getNumVertices();j++){ + vertex = element->getVertex(j); + p1 = SPoint3(vertex->x(),vertex->y(),vertex->z()); + it = vertex_to_vertices.find(vertex); + for(it2=(it->second).begin();it2!=(it->second).end();it2++){ + p2 = SPoint3((*it2)->x(),(*it2)->y(),(*it2)->z()); + print_segment(p1,p2,file); + } + } + } + file << "};\n"; +} + +void Recombinator::print_vertex_to_elements(GRegion* gr){ + int i,j; + MElement* element; + MVertex* vertex; + std::map<MVertex*,std::set<MElement*> >::iterator it; + std::map<MVertex*,std::set<MVertex*> >::iterator it2; + + for(i=0;i<gr->getNumMeshElements();i++){ + element = gr->getMeshElement(i); + for(j=0;j<element->getNumVertices();j++){ + vertex = element->getVertex(j); + it = vertex_to_elements.find(vertex); + it2 = vertex_to_vertices.find(vertex); + printf("%d %d\n",(it->second).size(),(it2->second).size()); + } + } +} + +void Recombinator::print_segment(SPoint3 p1,SPoint3 p2,std::ofstream& file){ + file << "SL (" + << p1.x() << ", " << p1.y() << ", " << p1.z() << ", " + << p2.x() << ", " << p2.y() << ", " << p2.z() << ")" + << "{10, 20};\n"; +} + +double Recombinator::scaled_jacobian(MVertex* a,MVertex* b,MVertex* c,MVertex* d){ + double val; + double l1,l2,l3; + SVector3 vec1,vec2,vec3; + + vec1 = SVector3(b->x()-a->x(),b->y()-a->y(),b->z()-a->z()); + vec2 = SVector3(c->x()-a->x(),c->y()-a->y(),c->z()-a->z()); + vec3 = SVector3(d->x()-a->x(),d->y()-a->y(),d->z()-a->z()); + + l1 = vec1.norm(); + l2 = vec2.norm(); + l3 = vec3.norm(); + + val = dot(vec1,crossprod(vec2,vec3)); + return fabs(val)/(l1*l2*l3); +} + +double Recombinator::max_scaled_jacobian(MElement* element,int& index){ + double val; + double j1,j2,j3,j4; + MVertex *a,*b,*c,*d; + + a = element->getVertex(0); + b = element->getVertex(1); + c = element->getVertex(2); + d = element->getVertex(3); + + j1 = scaled_jacobian(a,b,c,d); + j2 = scaled_jacobian(b,c,d,a); + j3 = scaled_jacobian(c,d,a,b); + j4 = scaled_jacobian(d,a,b,c); + + if(j1>=j2 && j1>=j3 && j1>=j4){ + index = 0; + val = j1; + } + else if(j2>=j3 && j2>=j4 && j2>=j1){ + index = 1; + val = j2; + } + else if(j3>=j4 && j3>=j1 && j3>=j2){ + index = 2; + val = j3; + } + else{ + index = 3; + val = j4; + } + + return val; +} + +double Recombinator::min_scaled_jacobian(Hex hex){ + int i; + double min; + double j1,j2,j3,j4,j5,j6,j7,j8; + MVertex *a,*b,*c,*d; + MVertex *e,*f,*g,*h; + std::vector<double> jacobians; + + a = hex.get_a(); + b = hex.get_b(); + c = hex.get_c(); + d = hex.get_d(); + e = hex.get_e(); + f = hex.get_f(); + g = hex.get_g(); + h = hex.get_h(); + + j1 = scaled_jacobian(a,b,d,e); + j2 = scaled_jacobian(b,a,c,f); + j3 = scaled_jacobian(c,b,d,g); + j4 = scaled_jacobian(d,a,c,h); + j5 = scaled_jacobian(e,a,f,h); + j6 = scaled_jacobian(f,b,e,g); + j7 = scaled_jacobian(g,c,f,h); + j8 = scaled_jacobian(h,d,e,g); + + jacobians.push_back(j1); + jacobians.push_back(j2); + jacobians.push_back(j3); + jacobians.push_back(j4); + jacobians.push_back(j5); + jacobians.push_back(j6); + jacobians.push_back(j7); + jacobians.push_back(j8); + + min = 1000000000.0; + for(i=0;i<8;i++){ + if(jacobians[i]<=min){ + min = jacobians[i]; + } + } + + return min; +} \ No newline at end of file diff --git a/Mesh/yamakawa.h b/Mesh/yamakawa.h new file mode 100755 index 0000000000000000000000000000000000000000..930190209a04d9075655ab3699095956dcc4d7b0 --- /dev/null +++ b/Mesh/yamakawa.h @@ -0,0 +1,89 @@ +// Gmsh - Copyright (C) 1997-2011 C. Geuzaine, J.-F. Remacle +// +// See the LICENSE.txt file for license information. Please report all +// bugs and problems to <gmsh@geuz.org>. +// +// Contributor(s): +// Tristan Carrier + +#include "GRegion.h" +#include <set> + +class Hex{ + private: + double quality; + MVertex *a,*b,*c,*d,*e,*f,*g,*h; + public: + Hex(); + Hex(MVertex*,MVertex*,MVertex*,MVertex*,MVertex*,MVertex*,MVertex*,MVertex*); + ~Hex(); + double get_quality() const; + void set_quality(double); + MVertex* get_a(); + MVertex* get_b(); + MVertex* get_c(); + MVertex* get_d(); + MVertex* get_e(); + MVertex* get_f(); + MVertex* get_g(); + MVertex* get_h(); + void set_vertices(MVertex*,MVertex*,MVertex*,MVertex*,MVertex*,MVertex*,MVertex*,MVertex*); + bool operator<(const Hex&) const; +}; + +class Recombinator{ + private: + std::vector<Hex> potential; + std::map<MElement*,bool> markings; + std::map<MVertex*,std::set<MVertex*> > vertex_to_vertices; + std::map<MVertex*,std::set<MElement*> > vertex_to_elements; + public: + Recombinator(); + ~Recombinator(); + + void execute(); + void execute(GRegion*); + + void init_markings(GRegion*); + void patern1(GRegion*); + void patern2(GRegion*); + void patern3(GRegion*); + void merge(GRegion*); + void rearrange(GRegion*); + void statistics(GRegion*); + + bool sliver(MElement*,Hex); + double diagonal(MElement*,int&,int&); + double distance(MVertex*,MVertex*); + double distance(MVertex*,MVertex*,MVertex*); + double scalar(MVertex*,MVertex*,MVertex*,MVertex*); + void two_others(int,int,int&,int&); + bool valid(Hex,const std::set<MElement*>&); + bool valid(Hex); + double eta(MVertex*,MVertex*,MVertex*,MVertex*); + bool linked(MVertex*,MVertex*); + + void find(MVertex*,MVertex*,const std::vector<MVertex*>&,std::set<MVertex*>&); + void find(MVertex*,MVertex*,MVertex*,const std::vector<MVertex*>&,std::set<MVertex*>&); + void find(MVertex*,MVertex*,std::set<MElement*>&); + void find(MVertex*,Hex,std::set<MElement*>&); + MVertex* find(MVertex*,MVertex*,MVertex*,MVertex*,const std::set<MElement*>&); + + void intersection(const std::set<MVertex*>&,const std::set<MVertex*>&,const std::vector<MVertex*>&,std::set<MVertex*>&); + void intersection(const std::set<MVertex*>&,const std::set<MVertex*>&,const std::set<MVertex*>&,const std::vector<MVertex*>&,std::set<MVertex*>&); + void intersection(const std::set<MElement*>&,const std::set<MElement*>&,std::set<MElement*>&); + + bool inclusion(MVertex*,Hex); + bool inclusion(MVertex*,MVertex*,MVertex*,MVertex*,MVertex*); + bool inclusion(MVertex*,MVertex*,MVertex*,const std::set<MElement*>&); + + void build_vertex_to_vertices(GRegion*); + void build_vertex_to_elements(GRegion*); + void print_vertex_to_vertices(GRegion*); + void print_vertex_to_elements(GRegion*); + void print_segment(SPoint3,SPoint3,std::ofstream&); + + double scaled_jacobian(MVertex*,MVertex*,MVertex*,MVertex*); + double max_scaled_jacobian(MElement*,int&); + double min_scaled_jacobian(Hex); +}; \ No newline at end of file diff --git a/wrappers/gmshpy/gmshMesh.i b/wrappers/gmshpy/gmshMesh.i index 963c0b8ff0d496c576f0c5fb4795302c2ba46c7d..e02347e94a9d0dc383fb7a618fdc46a8b871be09 100644 --- a/wrappers/gmshpy/gmshMesh.i +++ b/wrappers/gmshpy/gmshMesh.i @@ -24,6 +24,7 @@ #include "Levy3D.h" #include "periodical.h" #include "directions3D.h" + #include "yamakawa.h" #endif %} @@ -54,4 +55,5 @@ namespace std { %include "Levy3D.h" %include "periodical.h" %include "directions3D.h" +%include "yamakawa.h" #endif