diff --git a/Geo/MElementCut.cpp b/Geo/MElementCut.cpp index 3146757b26b505668c0aa8877291ba1b1825a268..b2817074c79a948846b427d59f8d738c0112493a 100644 --- a/Geo/MElementCut.cpp +++ b/Geo/MElementCut.cpp @@ -4,12 +4,13 @@ // bugs and problems to <gmsh@geuz.org>. #include <stdlib.h> +#include <sstream> #include "GmshConfig.h" #include "GModel.h" #include "MElement.h" #include "MElementCut.h" #include "gmshLevelset.h" -#include "MQuadrangle.h" +#include "MQuadrangle.h" #if defined(HAVE_DINTEGRATION) #include "Integration3D.h" @@ -452,12 +453,59 @@ void MLineBorder::getIntegrationPoints(int pOrder, int *npts, IntPt **pts) //---------------------------------------- CutMesh ---------------------------- static void assignPhysicals(GModel *GM, std::vector<int> &gePhysicals, int reg, int dim, - std::map<int, std::map<int, std::string> > physicals[4]) + std::map<int, std::map<int, std::string> > physicals[4], + std::map<int, int> &newPhysTags, int lsTag) { for(unsigned int i = 0; i < gePhysicals.size(); i++){ int phys = gePhysicals[i]; - if(phys && (!physicals[dim].count(reg) || !physicals[dim][reg].count(phys))) - physicals[dim][reg][phys] = GM->getPhysicalName(dim, phys); + + if(lsTag > 0 && newPhysTags.count(phys)){ + int phys2 = newPhysTags[phys]; + if(phys2 && (!physicals[dim].count(reg) || !physicals[dim][reg].count(phys2))){ + std::string name = GM->getPhysicalName(dim, phys); + if(name != "" && newPhysTags.count(-phys)){ + std::map<int, std::map<int, std::string> >::iterator it = physicals[dim].begin(); + for(; it != physicals[dim].end(); it++){ + std::map<int, std::string>::iterator it2 = it->second.begin(); + for(; it2 != it->second.end(); it2++) + if(it2->second == name) + physicals[dim][it->first][it2->first] = name + "_out"; + } + name += "_in"; + } + physicals[dim][reg][phys2] = name; + } + } + else if(lsTag < 0 && newPhysTags.count(-phys)){ + int phys2 = newPhysTags[-phys]; + if(phys2 && (!physicals[dim].count(reg) || !physicals[dim][reg].count(phys2))){ + std::string name = GM->getPhysicalName(dim, phys); + if(name != "" && newPhysTags.count(phys)){ + std::map<int, std::map<int, std::string> >::iterator it = physicals[dim].begin(); + for(; it != physicals[dim].end(); it++){ + std::map<int, std::string>::iterator it2 = it->second.begin(); + for(; it2 != it->second.end(); it2++) + if(it2->second == name) + physicals[dim][it->first][it2->first] = name + "_in"; + } + name += "_out"; + } + physicals[dim][reg][phys2] = name; + } + } + } +} + +static void assignLsPhysical(GModel *GM, int reg, int dim, + std::map<int, std::map<int, std::string> > physicals[4], + int physTag, int lsTag) +{ + if(!physicals[dim][reg].count(physTag)){ + std::stringstream strs; + strs << lsTag; + physicals[dim][reg][physTag] = "levelset_" + strs.str(); + if(physTag != lsTag) + Msg::Info("Levelset %d -> physical %d", lsTag, physTag); } } @@ -474,19 +522,17 @@ static int getElementaryTag(int lsTag, int elementary, std::map<int, int> &newEl } return elementary; } -static void getPhysicalTag(int lsTag, const std::vector<int> &physicals, - std::vector<int> &phys2, std::map<int, int> &newPhysTags) +static void getPhysicalTag(int lsTag, const std::vector<int> &physicals, std::map<int, int> &newPhysTags) { - phys2.clear(); - for(unsigned int i = 0; i < physicals.size(); i++){ int phys = physicals[i]; if(lsTag < 0){ - if(!newPhysTags.count(phys)) - newPhysTags[phys] = ++newPhysTags[0]; - phys = newPhysTags[phys]; + if(!newPhysTags.count(-phys)) + newPhysTags[-phys] = ++newPhysTags[0]; + phys = newPhysTags[-phys]; } - phys2.push_back(phys); + else if(!newPhysTags.count(phys)) + newPhysTags[phys] = phys; } } @@ -533,8 +579,7 @@ static void elementSplitMesh(MElement *e, fullMatrix<double> &verticesLs, case MSH_POLYH_ : { int reg = getElementaryTag(lsTag, elementary, newElemTags[3]); - std::vector<int> phys; - getPhysicalTag(lsTag, gePhysicals, phys, newPhysTags[3]); + getPhysicalTag(lsTag, gePhysicals, newPhysTags[3]); if(eType == MSH_TET_4) elements[4][reg].push_back(copy); else if(eType == MSH_HEX_8) @@ -545,7 +590,7 @@ static void elementSplitMesh(MElement *e, fullMatrix<double> &verticesLs, elements[7][reg].push_back(copy); else if(eType == MSH_POLYH_) elements[9][reg].push_back(copy); - assignPhysicals(GM, phys, reg, 3, physicals); + assignPhysicals(GM, gePhysicals, reg, 3, physicals, newPhysTags[3], lsTag); } break; case MSH_TRI_3 : @@ -554,34 +599,31 @@ static void elementSplitMesh(MElement *e, fullMatrix<double> &verticesLs, case MSH_POLYG_B : { int reg = getElementaryTag(lsTag, elementary, newElemTags[2]); - std::vector<int> phys; - getPhysicalTag(lsTag, gePhysicals, phys, newPhysTags[2]); + getPhysicalTag(lsTag, gePhysicals, newPhysTags[2]); if(eType == MSH_TRI_3) elements[2][reg].push_back(copy); else if(eType == MSH_QUA_4) elements[3][reg].push_back(copy); else if(eType == MSH_POLYG_ || eType == MSH_POLYG_B) elements[8][reg].push_back(copy); - assignPhysicals(GM, phys, reg, 2, physicals); + assignPhysicals(GM, gePhysicals, reg, 2, physicals, newPhysTags[2], lsTag); } break; case MSH_LIN_2 : case MSH_LIN_B : { int reg = getElementaryTag(lsTag, elementary, newElemTags[1]); - std::vector<int> phys; - getPhysicalTag(lsTag, gePhysicals, phys, newPhysTags[1]); + getPhysicalTag(lsTag, gePhysicals, newPhysTags[1]); elements[1][reg].push_back(copy); - assignPhysicals(GM, phys, reg, 1, physicals); + assignPhysicals(GM, gePhysicals, reg, 1, physicals, newPhysTags[1], lsTag); } break; case MSH_PNT : { int reg = getElementaryTag(lsTag, elementary, newElemTags[0]); - std::vector<int> phys; - getPhysicalTag(lsTag, gePhysicals, phys, newPhysTags[0]); + getPhysicalTag(lsTag, gePhysicals, newPhysTags[0]); elements[0][reg].push_back(copy); - assignPhysicals(GM, phys, reg, 0, physicals); + assignPhysicals(GM, gePhysicals, reg, 0, physicals, newPhysTags[0], lsTag); } break; default : @@ -786,16 +828,15 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN, p1 = new MPolyhedron(poly[0], n, ePart, own, parent); own = false; int reg = getElementaryTag(-1, elementary, newElemTags[3]); - std::vector<int> phys; - getPhysicalTag(-1, gePhysicals, phys, newPhysTags[3]); + getPhysicalTag(-1, gePhysicals, newPhysTags[3]); elements[9][reg].push_back(p1); - assignPhysicals(GM, phys, reg, 3, physicals); + assignPhysicals(GM, gePhysicals, reg, 3, physicals, newPhysTags[3], -1); } if(poly[1].size()) { int n = (e->getParent() && poly[0].size() == 0) ? e->getNum() : ++numEle; p2 = new MPolyhedron(poly[1], n, ePart, own, parent); elements[9][elementary].push_back(p2); - assignPhysicals(GM, gePhysicals, elementary, 3, physicals); + assignPhysicals(GM, gePhysicals, elementary, 3, physicals, newPhysTags[3], 1); } // check for border surfaces cut earlier along the polyhedra std::pair<std::multimap<MElement*, MElement*>::iterator, @@ -821,14 +862,13 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN, if(eParent) {copy->setParent(NULL, false); delete copy;} } else { // no cut - int tag ; - if (eType == TYPE_HEX) - tag = hexas[nbH]->lsTag(); + int lsTag; + if(eType == TYPE_HEX) + lsTag = hexas[nbH]->lsTag(); else - tag = tetras[nbTe]->lsTag(); - int reg = getElementaryTag(tag, elementary, newElemTags[3]); - std::vector<int> phys; - getPhysicalTag(tag, gePhysicals, phys, newPhysTags[3]); + lsTag = tetras[nbTe]->lsTag(); + int reg = getElementaryTag(lsTag, elementary, newElemTags[3]); + getPhysicalTag(lsTag, gePhysicals, newPhysTags[3]); if(eType == TYPE_TET) elements[4][reg].push_back(copy); else if(eType == TYPE_HEX) @@ -839,7 +879,7 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN, elements[7][reg].push_back(copy); else if(eType == TYPE_POLYH) elements[9][reg].push_back(copy); - assignPhysicals(GM, phys, reg, 3, physicals); + assignPhysicals(GM, gePhysicals, reg, 3, physicals, newPhysTags[3], lsTag); } for (unsigned int i = nbTr; i < triangles.size(); i++){ @@ -868,15 +908,13 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN, else tri = new MTriangleBorder(mv[0], mv[1], mv[2], ++numEle, ePart, p1, p2); } else tri = new MTriangle(mv[0], mv[1], mv[2], ++numEle, ePart); - int lsT = triangles[i]->lsTag(); - int c = elements[2].count(lsT) + elements[3].count(lsT) + elements[8].count(lsT); + int lsTag = triangles[i]->lsTag(); + int c = elements[2].count(lsTag) + elements[3].count(lsTag) + elements[8].count(lsTag); // the surfaces are cut before the volumes! - int reg = getBorderTag(lsT, c, newElemTags[2][0], borderElemTags[1]); - int physTag = (!gePhysicals.size()) ? 0 : getBorderTag(lsT, c, newPhysTags[2][0], borderPhysTags[1]); - std::vector<int> phys; - if(physTag) phys.push_back(physTag); + int reg = getBorderTag(lsTag, c, newElemTags[2][0], borderElemTags[1]); + int physTag = (!gePhysicals.size()) ? 0 : getBorderTag(lsTag, c, newPhysTags[2][0], borderPhysTags[1]); elements[2][reg].push_back(tri); - assignPhysicals(GM, phys, reg, 2, physicals); + assignLsPhysical(GM, reg, 2, physicals, physTag, lsTag); for(int i = 0; i < 2; i++) if(tri->getDomain(i)) borders[1].insert(std::pair<MElement*, MElement*>(tri->getDomain(i), tri)); @@ -985,10 +1023,9 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN, else p1 = new MPolygon(poly[0], n, ePart, own, parent); own = false; int reg = getElementaryTag(-1, elementary, newElemTags[2]); - std::vector<int> phys; - getPhysicalTag(-1, gePhysicals, phys, newPhysTags[2]); + getPhysicalTag(-1, gePhysicals, newPhysTags[2]); elements[8][reg].push_back(p1); - assignPhysicals(GM, phys, reg, 2, physicals); + assignPhysicals(GM, gePhysicals, reg, 2, physicals, newPhysTags[2], -1); for(int i = 0; i < 2; i++) if(p1->getDomain(i)) borders[1].insert(std::pair<MElement*, MElement*>(p1->getDomain(i), p1)); @@ -1000,7 +1037,7 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN, copy->getDomain(0), copy->getDomain(1)); else p2 = new MPolygon(poly[1], n, ePart, own, parent); elements[8][elementary].push_back(p2); - assignPhysicals(GM, gePhysicals, elementary, 2, physicals); + assignPhysicals(GM, gePhysicals, elementary, 2, physicals, newPhysTags[2], 1); for(int i = 0; i < 2; i++) if(p2->getDomain(i)) borders[1].insert(std::pair<MElement*, MElement*>(p2->getDomain(i), p2)); @@ -1028,21 +1065,20 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN, if(eParent) {copy->setParent(NULL, false); delete copy;} } else { // no cut - int tag; - if (eType == TYPE_QUA) - tag = quads[nbQ]->lsTag(); + int lsTag; + if(eType == TYPE_QUA) + lsTag = quads[nbQ]->lsTag(); else - tag = triangles[nbTr]->lsTag(); - int reg = getElementaryTag(tag, elementary, newElemTags[2]); - std::vector<int> phys; - getPhysicalTag(tag, gePhysicals, phys, newPhysTags[2]); + lsTag = triangles[nbTr]->lsTag(); + int reg = getElementaryTag(lsTag, elementary, newElemTags[2]); + getPhysicalTag(lsTag, gePhysicals, newPhysTags[2]); if(eType == TYPE_TRI) elements[2][reg].push_back(copy); else if(eType == TYPE_QUA) elements[3][reg].push_back(copy); else if(eType == TYPE_POLYG) elements[8][reg].push_back(copy); - assignPhysicals(GM, phys, reg, 2, physicals); + assignPhysicals(GM, gePhysicals, reg, 2, physicals, newPhysTags[2], lsTag); for(int i = 0; i < 2; i++) if(copy->getDomain(i)) borders[1].insert(std::pair<MElement*, MElement*>(copy->getDomain(i), copy)); @@ -1074,15 +1110,13 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN, else lin = new MLineBorder(mv[0], mv[1], ++numEle, ePart, p1, p2); } else lin = new MLine(mv[0], mv[1], ++numEle, ePart); - int lsL = lines[i]->lsTag(); - int c = elements[1].count(lsL); + int lsTag = lines[i]->lsTag(); + int c = elements[1].count(lsTag); // the lines are cut before the surfaces! - int reg = getBorderTag(lsL, c, newElemTags[1][0], borderElemTags[0]); - int physTag = (!gePhysicals.size()) ? 0 : getBorderTag(lsL, c, newPhysTags[1][0], borderPhysTags[0]); - std::vector<int> phys; - if(physTag) phys.push_back(physTag); + int reg = getBorderTag(lsTag, c, newElemTags[1][0], borderElemTags[0]); + int physTag = (!gePhysicals.size()) ? 0 : getBorderTag(lsTag, c, newPhysTags[1][0], borderPhysTags[0]); elements[1][reg].push_back(lin); - assignPhysicals(GM, phys, reg, 1, physicals); + assignLsPhysical(GM, reg, 1, physicals, physTag, lsTag); for(int i = 0; i < 2; i++) if(lin->getDomain(i)) borders[0].insert(std::pair<MElement*, MElement*>(lin->getDomain(i), lin)); @@ -1125,10 +1159,10 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN, copy->getDomain(0), copy->getDomain(1)); own = false; int reg = getElementaryTag(lines[i]->lsTag(), elementary, newElemTags[1]); - std::vector<int> phys; - getPhysicalTag(lines[i]->lsTag(), gePhysicals, phys, newPhysTags[1]); + int lsTag = lines[i]->lsTag(); + getPhysicalTag(lsTag, gePhysicals, newPhysTags[1]); elements[1][reg].push_back(ml); - assignPhysicals(GM, phys, reg, 1, physicals); + assignPhysicals(GM, gePhysicals, reg, 1, physicals, newPhysTags[1], lsTag); for(int i = 0; i < 2; i++) if(ml->getDomain(i)) borders[0].insert(std::pair<MElement*, MElement*>(ml->getDomain(i), ml)); @@ -1136,11 +1170,11 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN, if(eParent) {copy->setParent(NULL, false); delete copy;} } else { // no cut - int reg = getElementaryTag(lines[nbL]->lsTag(), elementary, newElemTags[1]); - std::vector<int> phys; - getPhysicalTag(lines[nbL]->lsTag(), gePhysicals, phys, newPhysTags[1]); + int lsTag = lines[nbL]->lsTag(); + int reg = getElementaryTag(lsTag, elementary, newElemTags[1]); + getPhysicalTag(lsTag, gePhysicals, newPhysTags[1]); elements[1][reg].push_back(copy); - assignPhysicals(GM, phys, reg, 1, physicals); + assignPhysicals(GM, gePhysicals, reg, 1, physicals, newPhysTags[1], lsTag); for(int i = 0; i < 2; i++) if(copy->getDomain(i)) borders[0].insert(std::pair<MElement*, MElement*>(copy->getDomain(i), copy)); @@ -1151,11 +1185,11 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN, { DI_Point P(e->getVertex(0)->x(), e->getVertex(0)->y(), e->getVertex(0)->z()); P.computeLs(RPN.back()); - int reg = getElementaryTag(P.lsTag(), elementary, newElemTags[0]); - std::vector<int> phys; - getPhysicalTag(P.lsTag(), gePhysicals, phys, newPhysTags[0]); + int lsTag = P.lsTag(); + int reg = getElementaryTag(lsTag, elementary, newElemTags[0]); + getPhysicalTag(lsTag, gePhysicals, newPhysTags[0]); elements[0][reg].push_back(copy); - assignPhysicals(GM, phys, reg, 0, physicals); + assignPhysicals(GM, gePhysicals, reg, 0, physicals, newPhysTags[0], lsTag); } break; default : @@ -1323,8 +1357,7 @@ GModel *buildCutMesh(GModel *gm, gLevelset *ls, if(!elements[1][nLR].empty()){ int newReg = ++newElemTags[1][0]; int newPhys = ++newPhysTags[1][0]; - std::vector<int> phys; phys.push_back(newPhys); - assignPhysicals(gm, phys, newReg, 1, physicals); + assignLsPhysical(gm, newReg, 1, physicals, newPhys, lines[lines.size() - 1]->lsTag()); for(int k = 0; k < conLines.size(); k++) elements[1][newReg].push_back(conLines[k]); }