diff --git a/Common/GmshDefines.h b/Common/GmshDefines.h index 8770d1b851ed929e06e3cddd3ca0907946cfc867..89f1a4e77622aa1e2ec66651d81dd4596ee0f607 100644 --- a/Common/GmshDefines.h +++ b/Common/GmshDefines.h @@ -197,7 +197,6 @@ #define MSH_PYR_245 131 // Additional types #define MSH_PYR_1 132 - #define MSH_PNT_SUB 133 #define MSH_LIN_SUB 134 #define MSH_TRI_SUB 135 diff --git a/Geo/GModelIO_MSH.cpp b/Geo/GModelIO_MSH.cpp index 73232135000dca622c650db97de970e1068ca60a..aa1210406db94c14df499eca95540312f02b93aa 100644 --- a/Geo/GModelIO_MSH.cpp +++ b/Geo/GModelIO_MSH.cpp @@ -129,8 +129,8 @@ int GModel::readMSH(const std::string &name) if(sscanf(str, "%d", &numVertices) != 1) return 0; Msg::Info("%d vertices", numVertices); Msg::ResetProgressMeter(); - std::map<int, MVertex*> vertexMap; - std::vector<MVertex*> vertexVector; + _vertexMapCache.clear(); + _vertexVectorCache.clear(); int maxVertex = -1; minVertex = numVertices + 1; for(int i = 0; i < numVertices; i++) { @@ -157,7 +157,7 @@ int GModel::readMSH(const std::string &name) case 0: { GVertex *gv = getVertexByTag(entity); - if (gv) gv->deleteMesh(); + if(gv) gv->deleteMesh(); vertex = new MVertex(xyz[0], xyz[1], xyz[2], gv, num); } break; @@ -166,7 +166,7 @@ int GModel::readMSH(const std::string &name) GEdge *ge = getEdgeByTag(entity); double u; if(!binary){ - if (fscanf(fp, "%lf", &u) != 1) return 0; + if(fscanf(fp, "%lf", &u) != 1) return 0; } else{ if(fread(&u, sizeof(double), 1, fp) != 1) return 0; @@ -180,7 +180,7 @@ int GModel::readMSH(const std::string &name) GFace *gf = getFaceByTag(entity); double uv[2]; if(!binary){ - if (fscanf(fp, "%lf %lf", &uv[0], &uv[1]) != 2) return 0; + if(fscanf(fp, "%lf %lf", &uv[0], &uv[1]) != 2) return 0; } else{ if(fread(uv, sizeof(double), 2, fp) != 2) return 0; @@ -210,32 +210,28 @@ int GModel::readMSH(const std::string &name) } minVertex = std::min(minVertex, num); maxVertex = std::max(maxVertex, num); - if(vertexMap.count(num)) + if(_vertexMapCache.count(num)) Msg::Warning("Skipping duplicate vertex %d", num); - vertexMap[num] = vertex; + _vertexMapCache[num] = vertex; if(numVertices > 100000) Msg::ProgressMeter(i + 1, numVertices, true, "Reading nodes"); } // if the vertex numbering is dense, transfer the map into a vector to // speed up element creation - if((int)vertexMap.size() == numVertices && + if((int)_vertexMapCache.size() == numVertices && ((minVertex == 1 && maxVertex == numVertices) || (minVertex == 0 && maxVertex == numVertices - 1))){ Msg::Info("Vertex numbering is dense"); - vertexVector.resize(vertexMap.size() + 1); + _vertexVectorCache.resize(_vertexMapCache.size() + 1); if(minVertex == 1) - vertexVector[0] = 0; + _vertexVectorCache[0] = 0; else - vertexVector[numVertices] = 0; - std::map<int, MVertex*>::const_iterator it = vertexMap.begin(); - for(; it != vertexMap.end(); ++it) - vertexVector[it->first] = it->second; - vertexMap.clear(); + _vertexVectorCache[numVertices] = 0; + for(std::map<int, MVertex*>::const_iterator it = _vertexMapCache.begin(); + it != _vertexMapCache.end(); ++it) + _vertexVectorCache[it->first] = it->second; + _vertexMapCache.clear(); } - - // cache the vertex indexing data - _vertexVectorCache = vertexVector; - _vertexMapCache = vertexMap; } // $Elements section @@ -245,79 +241,53 @@ int GModel::readMSH(const std::string &name) if(sscanf(str, "%d", &numElements) != 1) return 0; Msg::Info("%d elements", numElements); Msg::ResetProgressMeter(); - std::map<int, MElement*> elementMap; + _elementMapCache.clear(); for(int i = 0; i < numElements; i++) { - int num, type, numTags, numVertices; + int num, type, entity, numData; if(!binary){ - if(fscanf(fp, "%d %d %d", &num, &type, &numTags) != 3) return 0; + if(fscanf(fp, "%d %d %d %d", &num, &type, &entity, &numData) != 4) return 0; } else{ if(fread(&num, sizeof(int), 1, fp) != 1) return 0; if(swap) SwapBytes((char*)&num, sizeof(int), 1); if(fread(&type, sizeof(int), 1, fp) != 1) return 0; if(swap) SwapBytes((char*)&type, sizeof(int), 1); - if(fread(&numTags, sizeof(int), 1, fp) != 1) return 0; - if(swap) SwapBytes((char*)&numTags, sizeof(int), 1); + if(fread(&entity, sizeof(int), 1, fp) != 1) return 0; + if(swap) SwapBytes((char*)&entity, sizeof(int), 1); + if(fread(&numData, sizeof(int), 1, fp) != 1) return 0; + if(swap) SwapBytes((char*)&numData, sizeof(int), 1); } - std::vector<int> tags; - if(numTags > 0){ - tags.resize(numTags); + std::vector<int> data; + if(numData > 0){ + data.resize(numData); if(!binary){ - for(int j = 0; j < numTags; j++){ - if(fscanf(fp, "%d", &tags[j]) != 1) return 0; + for(int j = 0; j < numData; j++){ + if(fscanf(fp, "%d", &data[j]) != 1) return 0; } } else{ - if(fread(&tags[0], sizeof(int), numTags, fp) != numTags) return 0; - if(swap) SwapBytes((char*)&tags[0], sizeof(int), numTags); + if(fread(&data[0], sizeof(int), numData, fp) != numData) return 0; + if(swap) SwapBytes((char*)&data[0], sizeof(int), numData); } } - if(!(numVertices = MElement::getInfoMSH(type))) { - return 0; - } - std::vector<int> indices(numVertices); - if(!binary){ - for(int j = 0; j < numVertices; j++) - if(fscanf(fp, "%d", &indices[j]) != 1) return 0; - } - else{ - if(fread(&indices[0], sizeof(int), numVertices, fp) != numVertices) return 0; - if(swap) SwapBytes((char*)&indices[0], sizeof(int), numVertices); - } - std::vector<MVertex*> vertices; - if(_vertexVectorCache.size()){ - if(!getVertices(numVertices, indices, _vertexVectorCache, vertices, minVertex)) - return 0; - } - else{ - if(!getVertices(numVertices, indices, _vertexMapCache, vertices)) - return 0; - } - std::vector<short> ghosts; MElementFactory factory; - MElement *element = factory.create(num, type, tags, vertices, elementMap, - ghosts); - elementMap[num] = element; - int part = element->getPartition(); - if(part) getMeshPartitions().insert(part); - int elementary = tags.size() ? tags[0] : 0; + MElement *element = factory.create(num, type, data, this); switch(element->getType()){ - case TYPE_PNT: elements[0][elementary].push_back(element); break; - case TYPE_LIN: elements[1][elementary].push_back(element); break; - case TYPE_TRI: elements[2][elementary].push_back(element); break; - case TYPE_QUA: elements[3][elementary].push_back(element); break; - case TYPE_TET: elements[4][elementary].push_back(element); break; - case TYPE_HEX: elements[5][elementary].push_back(element); break; - case TYPE_PRI: elements[6][elementary].push_back(element); break; - case TYPE_PYR: elements[7][elementary].push_back(element); break; + case TYPE_PNT: elements[0][entity].push_back(element); break; + case TYPE_LIN: elements[1][entity].push_back(element); break; + case TYPE_TRI: elements[2][entity].push_back(element); break; + case TYPE_QUA: elements[3][entity].push_back(element); break; + case TYPE_TET: elements[4][entity].push_back(element); break; + case TYPE_HEX: elements[5][entity].push_back(element); break; + case TYPE_PRI: elements[6][entity].push_back(element); break; + case TYPE_PYR: elements[7][entity].push_back(element); break; + case TYPE_POLYG: elements[8][entity].push_back(element); break; + case TYPE_POLYH: elements[9][entity].push_back(element); break; } - for(unsigned int j = 0; j < ghosts.size(); j++) - _ghostCells.insert(std::pair<MElement*, short>(element, ghosts[j])); + _elementMapCache[num] = element; if(numElements > 100000) Msg::ProgressMeter(i + 1, numElements, true, "Reading elements"); } - // cache the element map - _elementMapCache = elementMap; } // Post-processing sections diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp index c1e8c2282d1f5a6618926d64a1a5721d5a82d537..18e6dc3b0d7f92a5a07a7a12594c943883a01adf 100644 --- a/Geo/MElement.cpp +++ b/Geo/MElement.cpp @@ -7,6 +7,7 @@ #include <math.h> #include "GmshConfig.h" #include "GmshMessage.h" +#include "GModel.h" #include "MElement.h" #include "MPoint.h" #include "MLine.h" @@ -710,7 +711,7 @@ double MElement::integrateFlux(double val[], int face, int pOrder, int order) return result; } -void MElement::writeMSH(FILE *fp, bool binary, int elementary, +void MElement::writeMSH(FILE *fp, bool binary, int entity, std::vector<short> *ghosts) { int num = getNum(); @@ -720,37 +721,40 @@ void MElement::writeMSH(FILE *fp, bool binary, int elementary, // if necessary, change the ordering of the vertices to get positive volume setVolumePositive(); - std::vector<int> info; - info.push_back(0); - info.push_back(elementary); + std::vector<int> verts; + getVerticesIdForMSH(verts); + + // FIXME: once we create elements using their own interpretion of data, we + // should move this also into each element base class + std::vector<int> data; + data.insert(data.end(), verts.begin(), verts.end()); if(getParent()) - info.push_back(getParent()->getNum()); + data.push_back(getParent()->getNum()); if(getPartition()){ if(ghosts){ - info.push_back(1 + ghosts->size()); - info.push_back(getPartition()); - info.insert(info.end(), ghosts->begin(), ghosts->end()); + data.push_back(1 + ghosts->size()); + data.push_back(getPartition()); + data.insert(data.end(), ghosts->begin(), ghosts->end()); } else{ - info.push_back(1); - info.push_back(getPartition()); + data.push_back(1); + data.push_back(getPartition()); } } - info[0] = info.size() - 1; - std::vector<int> verts; - getVerticesIdForMSH(verts); - info.insert(info.end(), verts.begin(), verts.end()); + int numData = data.size(); if(!binary){ - fprintf(fp, "%d %d", num, type); - for(unsigned int i = 0; i < info.size(); i++) - fprintf(fp, " %d", info[i]); + fprintf(fp, "%d %d %d %d", num, type, entity, numData); + for(unsigned int i = 0; i < numData; i++) + fprintf(fp, " %d", data[i]); fprintf(fp, "\n"); } else{ fwrite(&num, sizeof(int), 1, fp); fwrite(&type, sizeof(int), 1, fp); - fwrite(&info[0], sizeof(int), info.size(), fp); + fwrite(&entity, sizeof(int), 1, fp); + fwrite(&numData, sizeof(int), 1, fp); + fwrite(&data[0], sizeof(int), numData, fp); } } @@ -1389,30 +1393,55 @@ MElement *MElementFactory::create(int type, std::vector<MVertex*> &v, } } -MElement *MElementFactory::create(int num, int type, const std::vector<int> &tags, - std::vector<MVertex*> &v, - std::map<int, MElement*> &elementCache, - std::vector<short> &ghosts) +MElement *MElementFactory::create(int num, int type, const std::vector<int> &data, + GModel *model) { - MElement *parent = 0; - int part = 0; - if(tags.size() > 2 && (type == MSH_PNT_SUB || type == MSH_LIN_SUB || - type == MSH_TRI_SUB || type == MSH_TET_SUB)){ - parent = elementCache[tags[1]]; - if(tags.size() > 3 && tags[2]){ // num partitions - part = tags[3]; - for(int i = 0; i < tags[2] - 1; i++) - ghosts.push_back(tags[4 + i]); - } + // This should be rewritten: each element should register itself in a static + // factory owned e.g. directly by MElement, and interpret its data by + // itself. This would remove the ugly switch in the routine above. + + int numVertices = MElement::getInfoMSH(type), startVertices = 0; + if(data.size() && !numVertices){ + startVertices = 1; + numVertices = data[0]; + } + + std::vector<MVertex*> vertices(numVertices); + if(data.size() > startVertices + numVertices - 1){ + for(int i = 0; i < numVertices; i++) + vertices[i] = model->getMeshVertexByTag(data[startVertices + i]); } - else if(tags.size() > 1){ - if(tags[1]){ // num partitions - part = tags[2]; - for(int i = 0; i < tags[1] - 1; i++) - ghosts.push_back(tags[3 + i]); + else{ + return 0; + } + + int part = 0; + int startPartitions = startVertices + numVertices; + + MElement *parent = 0; + if((type == MSH_PNT_SUB || type == MSH_LIN_SUB || + type == MSH_TRI_SUB || type == MSH_TET_SUB)){ + parent = model->getMeshElementByTag(data[startPartitions]); + startPartitions += 1; + } + + std::vector<short> ghosts; + if(data.size() > startPartitions){ + int numPartitions = data[startPartitions]; + if(numPartitions > 0 && data.size() > startPartitions + numPartitions - 1){ + part = data[startPartitions + 1]; + for(int i = 1; i < numPartitions; i++) + ghosts.push_back(data[startPartitions + 1 + i]); } } - return create(type, v, num, part, false, parent); + + MElement *element = create(type, vertices, num, part, false, parent); + + for(unsigned int j = 0; j < ghosts.size(); j++) + model->getGhostCells().insert(std::pair<MElement*, short>(element, ghosts[j])); + if(part) model->getMeshPartitions().insert(part); + + return element; } void MElement::xyzTouvw(fullMatrix<double> *xu) diff --git a/Geo/MElement.h b/Geo/MElement.h index 7630b6664d4e0a5a298284b15e630c8fd94abcbf..67d48a6ca1d891c3923d1950a89f5a242d0c20b4 100644 --- a/Geo/MElement.h +++ b/Geo/MElement.h @@ -18,6 +18,8 @@ #include "JacobianBasis.h" #include "GaussIntegration.h" +class GModel; + // A mesh element. class MElement { @@ -357,10 +359,7 @@ class MElementFactory{ public: MElement *create(int type, std::vector<MVertex*> &v, int num=0, int part=0, bool owner=false, MElement *parent=0, MElement *d1=0, MElement *d2=0); - MElement *create(int num, int type, const std::vector<int> &tags, - std::vector<MVertex*> &v, - std::map<int, MElement*> &elementCache, - std::vector<short> &ghosts); + MElement *create(int num, int type, const std::vector<int> &data, GModel *model); }; // Traits of various elements based on the dimension. These generally define diff --git a/Geo/MSubElement.h b/Geo/MSubElement.h index 4f241d1facb678e4976873714dc7c45b58566f5a..53ba9bb60b63272a8c84e09bda06b3ce220cdb28 100644 --- a/Geo/MSubElement.h +++ b/Geo/MSubElement.h @@ -63,7 +63,8 @@ class MSubTriangle : public MTriangle MSubTriangle(MVertex *v0, MVertex *v1, MVertex *v2, int num=0, int part=0, bool owner=false, MElement* orig=NULL) : MTriangle(v0, v1, v2, num, part), _owner(owner), _orig(orig), _intpt(0) {} - MSubTriangle(std::vector<MVertex*> v, int num=0, int part=0, bool owner=false, MElement* orig=NULL) + MSubTriangle(std::vector<MVertex*> v, int num=0, int part=0, bool owner=false, + MElement* orig=NULL) : MTriangle(v, num, part), _owner(owner), _orig(orig), _intpt(0) {} ~MSubTriangle(); virtual int getTypeForMSH() const { return MSH_TRI_SUB; } @@ -94,9 +95,11 @@ class MSubLine : public MLine std::vector<MElement*> _parents; IntPt *_intpt; public: - MSubLine(MVertex *v0, MVertex *v1, int num=0, int part=0, bool owner=false, MElement* orig=NULL) + MSubLine(MVertex *v0, MVertex *v1, int num=0, int part=0, bool owner=false, + MElement* orig=NULL) : MLine(v0, v1, num, part), _owner(owner), _orig(orig), _intpt(0) {} - MSubLine(std::vector<MVertex*> v, int num=0, int part=0, bool owner=false, MElement* orig=NULL) + MSubLine(std::vector<MVertex*> v, int num=0, int part=0, bool owner=false, + MElement* orig=NULL) : MLine(v, num, part), _owner(owner), _orig(orig), _intpt(0) {} ~MSubLine(); virtual int getTypeForMSH() const { return MSH_LIN_SUB; } @@ -129,7 +132,8 @@ class MSubPoint : public MPoint public: MSubPoint(MVertex *v0, int num=0, int part=0, bool owner=false, MElement* orig=NULL) : MPoint(v0, num, part), _owner(owner), _orig(orig), _intpt(0) {} - MSubPoint(std::vector<MVertex*> v, int num=0, int part=0, bool owner=false, MElement* orig=NULL) + MSubPoint(std::vector<MVertex*> v, int num=0, int part=0, bool owner=false, + MElement* orig=NULL) : MPoint(v, num, part), _owner(owner), _orig(orig), _intpt(0) {} ~MSubPoint(); virtual int getTypeForMSH() const { return MSH_PNT_SUB; }