diff --git a/Post/PViewDataListIO.cpp b/Post/PViewDataListIO.cpp index b428507496145eb253b9a3e29cbd73a7afa84367..60efa68e91c5670452fabdddebd50fc6688846a1 100644 --- a/Post/PViewDataListIO.cpp +++ b/Post/PViewDataListIO.cpp @@ -10,6 +10,7 @@ #include "StringUtils.h" #include "GmshMessage.h" #include "GmshDefines.h" +#include "MVertexPositionSet.h" #include "Context.h" #include "adaptiveData.h" @@ -430,32 +431,8 @@ bool PViewDataList::writePOS(std::string fileName, bool binary, bool parsed, boo return true; } -class pVertex{ - public: - int Num; - double X, Y, Z; - std::vector<double> Val; - pVertex() : Num(0), X(0.), Y(0.), Z(0.) {} - pVertex(double x, double y, double z) : Num(0), X(x), Y(y), Z(z) {} -}; - -class pVertexLessThan{ - public: - bool operator()(const pVertex ent1, const pVertex ent2) const - { - double tol = CTX::instance()->lc * 1.e-10 ; - if(ent1.X - ent2.X > tol) return true; - if(ent1.X - ent2.X < -tol) return false; - if(ent1.Y - ent2.Y > tol) return true; - if(ent1.Y - ent2.Y < -tol) return false; - if(ent1.Z - ent2.Z > tol) return true; - return false; - } -}; - -static void getNodeMSH(int nbelm, std::vector<double> &list, - int nbnod, int nbcomp, int nbstep, - std::set<pVertex, pVertexLessThan> *nodes, int *numelm) +static void createVertices(std::vector<double> &list, int nbelm, int nbnod, + std::vector<MVertex*> &nodes) { if(!nbelm) return; int nb = list.size() / nbelm; @@ -463,84 +440,84 @@ static void getNodeMSH(int nbelm, std::vector<double> &list, double *x = &list[i]; double *y = &list[i + nbnod]; double *z = &list[i + 2 * nbnod]; - double *v = &list[i + 3 * nbnod]; - for(int j = 0; j < nbnod; j++) { - pVertex n(x[j], y[j], z[j]); - std::set<pVertex, pVertexLessThan>::iterator it = nodes->find(n); - if(it == nodes->end()){ - n.Num = nodes->size() + 1; - for(int ts = 0; ts < nbstep; ts++) - for(int k = 0; k < nbcomp; k++) - n.Val.push_back(v[nbcomp * nbnod * ts + nbcomp * j + k]); - nodes->insert(n); - } - } - (*numelm)++; - } + for(int j = 0; j < nbnod; j++) + nodes.push_back(new MVertex(x[j], y[j], z[j])); + } } -static void writeElementMSH(FILE *fp, int num, int nbnod, pVertex nod[8], - int nbcomp, double *vals, int dim) +static void createElements(std::vector<double> &list, int nbelm, int nbnod, + MVertexPositionSet &pos, std::vector<MElement*> &elements, + double eps, int type) { - switch(dim){ - case 0: - fprintf(fp, "%d 15 2 0 %d %d\n", num, num, nod[0].Num); + if(!nbelm) return; + int t = 0; + // reverse-engineer geometrical element type according to the number + // of nodes (this should be completed, but is likely enough for most + // legacy .pos files out there...) + switch(type){ + case TYPE_PNT : t = MSH_PNT; break; + case TYPE_LIN : + switch(nbnod){ + case 2: t = MSH_LIN_2; break; + case 3: t = MSH_LIN_3; break; + } break; - case 1: - fprintf(fp, "%d 1 0 %d %d\n", num, nod[0].Num, nod[1].Num); + case TYPE_TRI : + switch(nbnod){ + case 3: t = MSH_TRI_3; break; + case 6: t = MSH_TRI_6; break; + } break; - case 2: - if(nbnod == 3) - fprintf(fp, "%d 2 0 %d %d %d\n", num, nod[0].Num, nod[1].Num, nod[2].Num); - else - fprintf(fp, "%d 3 0 %d %d %d %d\n", num, nod[0].Num, nod[1].Num, - nod[2].Num, nod[3].Num); + case TYPE_QUA : + switch(nbnod){ + case 4: t = MSH_QUA_4; break; + case 8: t = MSH_QUA_8; break; + case 9: t = MSH_QUA_9; break; + } break; - case 3: - default: - if(nbnod == 4) - fprintf(fp, "%d 4 0 %d %d %d %d\n", num, nod[0].Num, nod[1].Num, - nod[2].Num, nod[3].Num); - else if(nbnod == 5) - fprintf(fp, "%d 7 0 %d %d %d %d %d\n", num, nod[0].Num, nod[1].Num, - nod[2].Num, nod[3].Num, nod[4].Num); - else if(nbnod == 6) - fprintf(fp, "%d 6 0 %d %d %d %d %d %d\n", num, nod[0].Num, nod[1].Num, - nod[2].Num, nod[3].Num, nod[4].Num, nod[5].Num); - else - fprintf(fp, "%d 5 0 %d %d %d %d %d %d %d %d\n", num, nod[0].Num, - nod[1].Num, nod[2].Num, nod[3].Num, nod[4].Num, nod[5].Num, - nod[6].Num, nod[7].Num); + case TYPE_TET : + switch(nbnod){ + case 4: t = MSH_TET_4; break; + case 10: t = MSH_TET_10; break; + } + break; + case TYPE_HEX : + switch(nbnod){ + case 8: t = MSH_HEX_8; break; + case 20: t = MSH_HEX_20; break; + case 27: t = MSH_HEX_27; break; + } + break; + case TYPE_PRI : + switch(nbnod){ + case 6: t = MSH_PRI_6; break; + case 15: t = MSH_PRI_15; break; + case 18: t = MSH_PRI_18; break; + } + break; + case TYPE_PYR : + switch(nbnod){ + case 5: t = MSH_PYR_5; break; + case 13: t = MSH_PYR_13; break; + case 14: t = MSH_PYR_14; break; + } break; } -} - -static void writeElementsMSH(FILE *fp, int nbelm, std::vector<double> &list, - int nbnod, int nbcomp, int dim, - std::set<pVertex, pVertexLessThan> *nodes, - int *numelm) -{ - if(!nbelm) return; - pVertex nod[8]; + if(!t){ + Msg::Warning("Discarding elements of type (%d nodes)", nbnod); + return; + } + MElementFactory factory; int nb = list.size() / nbelm; for(unsigned int i = 0; i < list.size(); i += nb){ double *x = &list[i]; double *y = &list[i + nbnod]; double *z = &list[i + 2 * nbnod]; - double *v = &list[i + 3 * nbnod]; - for(int j = 0; j < nbnod; j++) { - pVertex n(x[j], y[j], z[j]); - std::set<pVertex, pVertexLessThan>::iterator it = nodes->find(n); - if(it == nodes->end()){ - Msg::Error("Unknown node in element"); - return; - } - else{ - nod[j] = (pVertex)(*it); - } - } - (*numelm)++; - writeElementMSH(fp, *numelm, nbnod, nod, nbcomp, v, dim); + std::vector<MVertex*> verts(nbnod); + for(int j = 0; j < nbnod; j++) + verts[j] = pos.find(x[j], y[j], z[j], eps); + MElement *e = factory.create(t, verts); + elements.push_back(e); } } @@ -550,11 +527,6 @@ bool PViewDataList::writeMSH(std::string fileName, bool binary, bool savemesh) Msg::Warning("Writing adapted dataset (will only export current time step)"); return _adaptive->getData()->writeMSH(fileName, binary); } - else if(haveInterpolationMatrices()){ - Msg::Error("Cannot (yet) export datasets with interpolation matrices: use"); - Msg::Error("'Adapt visualization grid' before exporting!"); - return false; - } FILE *fp = fopen(fileName.c_str(), "w"); if(!fp){ @@ -562,90 +534,100 @@ bool PViewDataList::writeMSH(std::string fileName, bool binary, bool savemesh) return false; } - if(binary) Msg::Warning("Binary write not implemented yet"); - - std::set<pVertex, pVertexLessThan> nodes; - int numelm = 0; - getNodeMSH(NbSP, SP, 1, 1, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbVP, VP, 1, 3, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbTP, TP, 1, 9, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbSL, SL, 2, 1, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbVL, VL, 2, 3, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbTL, TL, 2, 9, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbST, ST, 3, 1, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbVT, VT, 3, 3, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbTT, TT, 3, 9, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbSQ, SQ, 4, 1, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbVQ, VQ, 4, 3, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbTQ, TQ, 4, 9, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbSS, SS, 4, 1, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbVS, VS, 4, 3, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbTS, TS, 4, 9, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbSH, SH, 8, 1, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbVH, VH, 8, 3, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbTH, TH, 8, 9, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbSI, SI, 6, 1, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbVI, VI, 6, 3, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbTI, TI, 6, 9, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbSY, SY, 5, 1, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbVY, VY, 5, 3, NbTimeStep, &nodes, &numelm); - getNodeMSH(NbTY, TY, 5, 9, NbTimeStep, &nodes, &numelm); - fprintf(fp, "$MeshFormat\n2 0 8\n$EndMeshFormat\n"); + double tol = CTX::instance()->geom.tolerance; + double eps = norm(SVector3(BBox.max(), BBox.min())) * tol; + + std::vector<MVertex*> vertices; + std::vector<MElement*> elements; + + int numComponents = 9; + for(int i = 0; i < 24; i++){ + std::vector<double> *list = 0; + int *numEle = 0, numNodes, numComp; + _getRawData(i, &list, &numEle, &numComp, &numNodes); + if(*numEle) numComponents = std::min(numComponents, numComp); + createVertices(*list, *numEle, numNodes, vertices); + } + MVertexPositionSet pos(vertices); + + for(int i = 0; i < 24; i++){ + std::vector<double> *list = 0; + int *numEle = 0, numComp, numNodes; + int typ = _getRawData(i, &list, &numEle, &numComp, &numNodes); + createElements(*list, *numEle, numNodes, pos, elements, eps, typ); + } + + int num = 0; + for(unsigned int i = 0; i < vertices.size(); i++) + if(vertices[i]->getIndex() < 0) + vertices[i]->setIndex(++num); + + fprintf(fp, "$MeshFormat\n2.2 0 8\n$EndMeshFormat\n"); fprintf(fp, "$Nodes\n"); - fprintf(fp, "%d\n", (int)nodes.size()); - for(std::set<pVertex, pVertexLessThan>::iterator it = nodes.begin(); - it != nodes.end(); ++it){ - fprintf(fp, "%d %.16g %.16g %.16g\n", it->Num, it->X, it->Y, it->Z); + fprintf(fp, "%d\n", num); + for(unsigned int i = 0; i < vertices.size(); i++){ + MVertex *v = vertices[i]; + if(v->getIndex() > 0) + fprintf(fp, "%d %.16g %.16g %.16g\n", v->getIndex(), v->x(), v->y(), v->z()); } fprintf(fp, "$EndNodes\n"); fprintf(fp, "$Elements\n"); - fprintf(fp, "%d\n", numelm); - numelm = 0; - writeElementsMSH(fp, NbSP, SP, 1, 1, 0, &nodes, &numelm); - writeElementsMSH(fp, NbVP, VP, 1, 3, 0, &nodes, &numelm); - writeElementsMSH(fp, NbTP, TP, 1, 9, 0, &nodes, &numelm); - writeElementsMSH(fp, NbSL, SL, 2, 1, 1, &nodes, &numelm); - writeElementsMSH(fp, NbVL, VL, 2, 3, 1, &nodes, &numelm); - writeElementsMSH(fp, NbTL, TL, 2, 9, 1, &nodes, &numelm); - writeElementsMSH(fp, NbST, ST, 3, 1, 2, &nodes, &numelm); - writeElementsMSH(fp, NbVT, VT, 3, 3, 2, &nodes, &numelm); - writeElementsMSH(fp, NbTT, TT, 3, 9, 2, &nodes, &numelm); - writeElementsMSH(fp, NbSQ, SQ, 4, 1, 2, &nodes, &numelm); - writeElementsMSH(fp, NbVQ, VQ, 4, 3, 2, &nodes, &numelm); - writeElementsMSH(fp, NbTQ, TQ, 4, 9, 2, &nodes, &numelm); - writeElementsMSH(fp, NbSS, SS, 4, 1, 3, &nodes, &numelm); - writeElementsMSH(fp, NbVS, VS, 4, 3, 3, &nodes, &numelm); - writeElementsMSH(fp, NbTS, TS, 4, 9, 3, &nodes, &numelm); - writeElementsMSH(fp, NbSH, SH, 8, 1, 3, &nodes, &numelm); - writeElementsMSH(fp, NbVH, VH, 8, 3, 3, &nodes, &numelm); - writeElementsMSH(fp, NbTH, TH, 8, 9, 3, &nodes, &numelm); - writeElementsMSH(fp, NbSI, SI, 6, 1, 3, &nodes, &numelm); - writeElementsMSH(fp, NbVI, VI, 6, 3, 3, &nodes, &numelm); - writeElementsMSH(fp, NbTI, TI, 6, 9, 3, &nodes, &numelm); - writeElementsMSH(fp, NbSY, SY, 5, 1, 3, &nodes, &numelm); - writeElementsMSH(fp, NbVY, VY, 5, 3, 3, &nodes, &numelm); - writeElementsMSH(fp, NbTY, TY, 5, 9, 3, &nodes, &numelm); + fprintf(fp, "%d\n", (int)elements.size()); + for(unsigned int i = 0; i < elements.size(); i++) + elements[i]->writeMSH(fp, 2.2, false, i + 1); fprintf(fp, "$EndElements\n"); - int numNodes = nodes.size(); - if(numNodes){ - int numComp = nodes.begin()->Val.size() / NbTimeStep; - for(int ts = 0; ts < NbTimeStep; ts++){ - double time = getTime(ts); - fprintf(fp, "$NodeData\n"); + if(haveInterpolationMatrices()){ + fprintf(fp, "$InterpolationScheme\n"); + fprintf(fp, "\"INTERPOLATION_SCHEME\"\n"); + fprintf(fp, "%d\n", (int)_interpolation.size()); + for(interpolationMatrices::iterator it = _interpolation.begin(); + it != _interpolation.end(); it++){ + if(it->second.size() >= 2){ + fprintf(fp, "%d\n2\n", it->first); + for(int mat = 0; mat < 2; mat++){ + int m = it->second[mat]->size1(), n = it->second[mat]->size2(); + fprintf(fp, "%d %d\n", m, n); + for(int i = 0; i < m; i++){ + for(int j = 0; j < n; j++) + fprintf(fp, "%.16g ", it->second[mat]->get(i, j)); + fprintf(fp, "\n"); + } + } + } + } + fprintf(fp, "$EndInterpolationScheme\n"); + } + + for(int ts = 0; ts < NbTimeStep; ts++){ + fprintf(fp, "$ElementNodeData\n"); + if(haveInterpolationMatrices()) + fprintf(fp, "2\n\"%s\"\n\"INTERPOLATION_SCHEME\"\n", getName().c_str()); + else fprintf(fp, "1\n\"%s\"\n", getName().c_str()); - fprintf(fp, "1\n%.16g\n", time); - fprintf(fp, "3\n%d\n%d\n%d\n", ts, numComp, numNodes); - for(std::set<pVertex, pVertexLessThan>::iterator it = nodes.begin(); - it != nodes.end(); ++it){ - fprintf(fp, "%d", it->Num); - for(int i = 0; i < numComp; i++) - fprintf(fp, " %.16g", it->Val[ts * numComp + i]); - fprintf(fp, "\n"); + fprintf(fp, "1\n%.16g\n", getTime(ts)); + fprintf(fp, "3\n%d\n%d\n%d\n", ts, numComponents, (int)elements.size()); + num = 0; + for(int i = 0; i < 24; i++){ + std::vector<double> *list = 0; + int *numEle = 0, numComp, numNodes; + int typ = _getRawData(i, &list, &numEle, &numComp, &numNodes); + if(*numEle){ + int mult = numNodes; + if(_interpolation.count(typ)) + mult = _interpolation[typ][0]->size1(); + int nb = list->size() / *numEle; + for(unsigned int i = 0; i < list->size(); i += nb){ + double *v = &(*list)[i + 3 * numNodes]; + fprintf(fp, "%d %d", ++num, mult); + for(int j = 0; j < numComponents * mult; j++) + fprintf(fp, " %.16g", v[numComponents * mult * ts + j]); + fprintf(fp, "\n"); + } } - fprintf(fp, "$EndNodeData\n"); } + fprintf(fp, "$EndElementNodeData\n"); } fclose(fp);