35 bool renumber,
bool saveAll);
40 std::map<int, MVertex *> &map,
41 std::vector<MVertex *> &vertices)
43 for(
int i = 0; i < num; i++) {
44 if(!map.count(indices[i])) {
49 vertices.push_back(map[indices[i]]);
55 std::vector<MVertex *> &vertices,
int minVertex = 0)
57 for(
int i = 0; i < num; i++) {
58 if(indices[i] < minVertex ||
59 indices[i] > (
int)(vec.size() - 1 + minVertex)) {
64 vertices.push_back(vec[indices[i]]);
71 unsigned int part, std::vector<MVertex *> &v,
72 std::map<
int, std::vector<MElement *> > elements[10],
73 std::map<
int, std::map<int, std::string> > physicals[4],
74 bool owner =
false,
MElement *parent =
nullptr,
84 MElement *e = factory.
create(typeMSH, v, num, part, owner, 0, parent, d1, d2);
87 Msg::Error(
"Unknown type of element %d", typeMSH);
93 (!physicals[dim].count(reg) || !physicals[dim][reg].count(physical)))
94 physicals[dim][reg][physical] =
"unnamed";
102 FILE *fp =
Fopen(name.c_str(),
"rb");
104 Msg::Error(
"Unable to open file '%s'", name.c_str());
108 char str[256] =
"XXX";
109 double version = 1.0;
110 bool binary =
false,
swap =
false, postpro =
false;
111 std::map<int, std::vector<MElement *> > elements[10];
112 std::map<int, std::map<int, std::string> > physicals[4];
113 std::map<int, MVertex *> vertexMap;
114 std::vector<MVertex *> vertexVector;
119 while(str[0] !=
'$') {
120 if(!fgets(str,
sizeof(str), fp) || feof(fp))
break;
125 if(!strncmp(&str[1],
"MeshFormat", 10)) {
126 if(!fgets(str,
sizeof(str), fp)) {
131 if(sscanf(str,
"%lf %d %d", &version, &format, &size) != 3) {
139 if(fread(&one,
sizeof(
int), 1, fp) != 1) {
145 Msg::Debug(
"Swapping bytes from binary file");
149 else if(!strncmp(&str[1],
"PhysicalNames", 13)) {
150 if(!fgets(str,
sizeof(str), fp)) {
155 if(sscanf(str,
"%d", &numNames) != 1) {
159 for(
int i = 0; i < numNames; i++) {
162 if(fscanf(fp,
"%d", &dim) != 1) {
167 if(fscanf(fp,
"%d", &num) != 1) {
171 if(!fgets(str,
sizeof(str), fp)) {
179 else if(!strncmp(&str[1],
"NO", 2) || !strncmp(&str[1],
"Nodes", 5) ||
180 !strncmp(&str[1],
"ParametricNodes", 15)) {
181 const bool parametric = !strncmp(&str[1],
"ParametricNodes", 15);
182 if(!fgets(str,
sizeof(str), fp)) {
186 int numVertices = -1;
187 if(sscanf(str,
"%d", &numVertices) != 1) {
193 vertexVector.clear();
195 minVertex = numVertices + 1;
197 for(
int i = 0; i < numVertices; i++) {
199 double xyz[3], uv[2];
203 if(fscanf(fp,
"%d %lf %lf %lf", &num, &xyz[0], &xyz[1], &xyz[2]) !=
210 if(fread(&num,
sizeof(
int), 1, fp) != 1) {
215 if(fread(xyz,
sizeof(
double), 3, fp) != 3) {
221 newVertex =
new MVertex(xyz[0], xyz[1], xyz[2],
nullptr, num);
224 int iClasDim, iClasTag;
226 if(fscanf(fp,
"%d %lf %lf %lf %d %d", &num, &xyz[0], &xyz[1],
227 &xyz[2], &iClasDim, &iClasTag) != 6) {
233 if(fread(&num,
sizeof(
int), 1, fp) != 1) {
238 if(fread(xyz,
sizeof(
double), 3, fp) != 3) {
243 if(fread(&iClasDim,
sizeof(
int), 1, fp) != 1) {
248 if(fread(&iClasTag,
sizeof(
int), 1, fp) != 1) {
257 newVertex =
new MVertex(xyz[0], xyz[1], xyz[2], gv, num);
259 else if(iClasDim == 1) {
262 if(fscanf(fp,
"%lf", &uv[0]) != 1) {
268 if(fread(uv,
sizeof(
double), 1, fp) != 1) {
274 newVertex =
new MEdgeVertex(xyz[0], xyz[1], xyz[2], ge, uv[0], num);
276 else if(iClasDim == 2) {
279 if(fscanf(fp,
"%lf %lf", &uv[0], &uv[1]) != 2) {
285 if(fread(uv,
sizeof(
double), 2, fp) != 2) {
292 new MFaceVertex(xyz[0], xyz[1], xyz[2], gf, uv[0], uv[1], num);
294 else if(iClasDim == 3) {
296 newVertex =
new MVertex(xyz[0], xyz[1], xyz[2], gr, num);
299 minVertex = std::min(minVertex, num);
300 maxVertex = std::max(maxVertex, num);
301 if(vertexMap.count(num))
303 vertexMap[num] = newVertex;
304 if(numVertices > 100000)
310 if((
int)vertexMap.size() == numVertices &&
311 ((minVertex == 1 && maxVertex == numVertices) ||
312 (minVertex == 0 && maxVertex == numVertices - 1))) {
314 vertexVector.resize(vertexMap.size() + 1);
316 vertexVector[0] =
nullptr;
318 vertexVector[numVertices] =
nullptr;
319 for(
auto it = vertexMap.begin(); it != vertexMap.end(); ++it)
320 vertexVector[it->first] = it->second;
324 else if(!strncmp(&str[1],
"ELM", 3) || !strncmp(&str[1],
"Elements", 8)) {
325 if(!fgets(str,
sizeof(str), fp)) {
331 std::map<int, MElement *> elems;
332 std::map<int, MElement *> parents;
333 std::map<int, MElement *> domains;
334 std::map<int, int> elemreg;
335 std::map<int, int> elemphy;
337 std::set<MElement *> parentsOwned;
338 sscanf(str,
"%d", &numElements);
342 for(
int i = 0; i < numElements; i++) {
343 int num, type, physical = 0, elementary = 0, partition = 0,
345 int dom1 = 0, dom2 = 0, numVertices;
346 std::vector<short> ghosts;
348 if(fscanf(fp,
"%d %d %d %d %d", &num, &type, &physical, &elementary,
349 &numVertices) != 5) {
360 if(fscanf(fp,
"%d %d %d", &num, &type, &numTags) != 3) {
364 int numPartitions = 0;
365 for(
int j = 0; j < numTags; j++) {
367 if(fscanf(fp,
"%d", &tag) != 1) {
375 else if(version < 2.2 && j == 2)
377 else if(version >= 2.2 && j == 2 && numTags > 3)
379 else if(version >= 2.2 && j == 3)
381 else if(j >= 4 && j < 4 + numPartitions - 1)
382 ghosts.push_back(-tag);
383 else if(j == 3 + numPartitions && (numTags == 4 + numPartitions))
385 else if(j == 3 + numPartitions &&
386 (numTags == 5 + numPartitions)) {
389 if(fscanf(fp,
"%d", &dom2) != 1) {
401 if(fscanf(fp,
"%d", &numVertices) != 1) {
407 int *indices =
new int[numVertices];
408 for(
int j = 0; j < numVertices; j++) {
409 if(fscanf(fp,
"%d", &indices[j]) != 1) {
416 if(vertexVector.size()) {
436 auto ite = elems.find(parent);
437 if(ite == elems.end())
439 "Parent element (ascii) %d not found for element %d of type %d",
445 auto itpo = parentsOwned.find(p);
446 if(itpo == parentsOwned.end()) {
448 parentsOwned.insert(p);
450 assert(p !=
nullptr);
454 MElement *doms[2] = {
nullptr,
nullptr};
456 auto ite = elems.find(dom1);
457 if(ite == elems.end())
458 Msg::Error(
"Domain element %d not found for element %d", dom1,
461 doms[0] = ite->second;
463 ite = elems.find(dom2);
464 if(ite != elems.end()) doms[1] = ite->second;
467 Msg::Error(
"Domain element %d not found for element %d", dom1,
470 Msg::Error(
"Domain element %d not found for element %d", dom2,
475 if(elementary < 0)
continue;
478 physicals, own, p, doms[0], doms[1]);
480 elemreg[num] = elementary;
481 elemphy[num] = physical;
482 for(std::size_t j = 0; j < ghosts.size(); j++)
483 _ghostCells.insert(std::pair<MElement *, short>(e, ghosts[j]));
484 if(numElements > 100000)
489 int numElementsPartial = 0;
490 while(numElementsPartial < numElements) {
492 if(fread(header,
sizeof(
int), 3, fp) != 3) {
497 int type = header[0];
498 int numElms = header[1];
499 int numTags = header[2];
501 unsigned int n = 1 + numTags + numVertices;
502 int *data =
new int[n];
503 for(
int i = 0; i < numElms; i++) {
504 if(fread(data,
sizeof(
int), n, fp) != n) {
511 int physical = (numTags > 0) ? data[1] : 0;
512 int elementary = (numTags > 1) ? data[2] : 0;
513 int numPartitions = (version >= 2.2 && numTags > 3) ? data[3] : 0;
514 int partition = (version < 2.2 && numTags > 2) ? data[3] :
515 (version >= 2.2 && numTags > 3) ? data[4] :
517 int parent = (version < 2.2 && numTags > 3) ||
518 (version >= 2.2 && numPartitions &&
519 numTags > 3 + numPartitions) ||
520 (version >= 2.2 && !numPartitions && numTags > 2) ?
523 int *indices = &data[numTags + 1];
525 if(vertexVector.size()) {
543 auto ite = elems.find(parent);
544 if(ite == elems.end())
546 "Parent (binary) element %d not found for element %d", parent,
552 auto itpo = parentsOwned.find(p);
553 if(itpo == parentsOwned.end()) {
555 parentsOwned.insert(p);
557 assert(p !=
nullptr);
561 elements, physicals, own, p);
563 elemreg[num] = elementary;
564 elemphy[num] = physical;
565 if(numPartitions > 1)
566 for(
int j = 0; j < numPartitions - 1; j++)
568 std::pair<MElement *, short>(e, -data[5 + j]));
569 if(numElements > 100000)
574 numElementsPartial += numElms;
579 for(
int i = 0; i < 10; i++) elements[i].clear();
581 for(
auto ite = elems.begin(); ite != elems.end(); ite++) {
582 int num = ite->first;
584 if(parents.find(num) == parents.end()) {
591 case TYPE_PNT: elements[0][reg].push_back(e);
break;
592 case TYPE_LIN: elements[1][reg].push_back(e);
break;
593 case TYPE_TRI: elements[2][reg].push_back(e);
break;
594 case TYPE_QUA: elements[3][reg].push_back(e);
break;
595 case TYPE_TET: elements[4][reg].push_back(e);
break;
596 case TYPE_HEX: elements[5][reg].push_back(e);
break;
597 case TYPE_PRI: elements[6][reg].push_back(e);
break;
598 case TYPE_PYR: elements[7][reg].push_back(e);
break;
599 case TYPE_POLYG: elements[8][reg].push_back(e);
break;
600 case TYPE_POLYH: elements[9][reg].push_back(e);
break;
609 else if(!strncmp(&str[1],
"NodeData", 8)) {
612 if(vertexVector.size())
619 else if(!strncmp(&str[1],
"ElementData", 11) ||
620 !strncmp(&str[1],
"ElementNodeData", 15)) {
627 if(!fgets(str,
sizeof(str), fp) || feof(fp))
break;
628 }
while(str[0] !=
'$');
633 for(
int i = 0; i < (int)(
sizeof(elements) /
sizeof(elements[0])); i++)
640 if(vertexVector.size())
658 while(str[0] !=
'$') {
659 if(!fgets(str,
sizeof(str), fp) || feof(fp))
break;
663 if(!strncmp(&str[1],
"Periodic", 8) &&
664 strncmp(&str[1],
"PeriodicNodes", 13)) {
669 if(!fgets(str,
sizeof(str), fp) || feof(fp))
break;
670 }
while(str[0] !=
'$');
691 return postpro ? 2 : 1;
696 bool saveAll,
double version,
bool binary,
int &num,
697 int elementary, std::vector<int> &physicals,
698 int parentNum = 0,
int dom1Num = 0,
int dom2Num = 0)
710 std::vector<short> ghosts;
713 for(
auto it = itp.first; it != itp.second; it++)
714 ghosts.push_back(it->second);
718 ele->writeMSH2(fp, version, binary, ++num, elementary, 0, parentNum,
719 dom1Num, dom2Num, &ghosts);
721 if(parentNum) parentNum = parentNum - physicals.size() + 1;
722 for(std::size_t j = 0; j < physicals.size(); j++) {
723 ele->writeMSH2(fp, version, binary, ++num, elementary, physicals[j],
724 parentNum, dom1Num, dom2Num, &ghosts);
725 if(parentNum) parentNum++;
732 num += ele->getNumChildren() - 1;
737 std::vector<T *> &ele,
bool saveAll,
738 int saveSinglePartition,
double version,
739 bool binary,
int &num,
int elementary,
740 std::vector<int> &physicals)
753 if(saveSinglePartition < 0) {
754 if(ele.empty())
return;
755 int offset = -saveSinglePartition;
757 for(std::size_t i = 0; i < ele.size(); i++) {
758 std::vector<int> newPhysicals;
759 int newElementary = elementary;
761 newElementary = elementary * offset + ele[i]->getPartition();
762 for(std::size_t j = 0; j < physicals.size(); j++)
763 newPhysicals.push_back(physicals[j] * offset +
764 ele[i]->getPartition());
766 else if(elementary < 0) {
767 newPhysicals.push_back((maxPhysical - elementary) * offset);
769 ele[i]->setPartition(0);
771 newElementary, newPhysicals);
776 for(std::size_t i = 0; i < ele.size(); i++) {
777 if(saveSinglePartition && ele[i]->getPartition() != saveSinglePartition)
779 if(ele[i]->getDomain(0))
continue;
784 elementary, physicals, parentNum);
800 int n = 0, p = saveAll ? 1 : ge->
physicals.size();
802 if(saveSinglePartition < 0 && ge->tag() < 0) p = 1;
804 if(saveSinglePartition <= 0)
818 for(std::size_t i = 0; i < (*it)->points.size(); i++)
819 if((*it)->points[i]->ownsParent())
820 n += (saveAll ? 1 : (*it)->physicals.size());
826 for(std::size_t i = 0; i < (*it)->lines.size(); i++)
827 if((*it)->lines[i]->ownsParent())
828 n += (saveAll ? 1 : (*it)->physicals.size());
834 for(std::size_t i = 0; i < (*it)->polygons.size(); i++) {
835 int nbC = (*it)->polygons[i]->getNumChildren() - 1;
836 n += (saveAll ? nbC : nbC * (*it)->physicals.size());
840 for(std::size_t i = 0; i < (*it)->triangles.size(); i++)
841 if((*it)->triangles[i]->ownsParent())
842 n += (saveAll ? 1 : (*it)->physicals.size());
843 for(std::size_t i = 0; i < (*it)->polygons.size(); i++)
844 if((*it)->polygons[i]->ownsParent())
845 n += (saveAll ? 1 : (*it)->physicals.size());
851 for(std::size_t i = 0; i < (*it)->polyhedra.size(); i++) {
852 int nbC = (*it)->polyhedra[i]->getNumChildren() - 1;
853 n += (saveAll ? nbC : nbC * (*it)->physicals.size());
857 for(std::size_t i = 0; i < (*it)->tetrahedra.size(); i++)
858 if((*it)->tetrahedra[i]->ownsParent())
859 n += (saveAll ? 1 : (*it)->physicals.size());
860 for(std::size_t i = 0; i < (*it)->polyhedra.size(); i++)
861 if((*it)->polyhedra[i]->ownsParent())
862 n += (saveAll ? 1 : (*it)->physicals.size());
864 n -= (*it)->trihedra.size();
884 bool saveAll,
bool saveParametric,
double scalingFactor,
885 int elementStartNum,
int saveSinglePartition,
886 bool append,
bool renumberVertices)
890 fp =
Fopen(name.c_str(), binary ?
"ab" :
"a");
892 fp =
Fopen(name.c_str(), binary ?
"wb" :
"w");
894 Msg::Error(
"Unable to open file '%s'", name.c_str());
899 if(version > 1 || binary)
917 fprintf(fp,
"$MeshFormat\n");
918 fprintf(fp,
"%g %d %d\n", version, binary ? 1 : 0, (
int)
sizeof(
double));
921 fwrite(&one,
sizeof(
int), 1, fp);
924 fprintf(fp,
"$EndMeshFormat\n");
927 fprintf(fp,
"$PhysicalNames\n");
930 std::string name = it->second;
931 if(name.size() > 128) name.resize(128);
932 fprintf(fp,
"%d %d \"%s\"\n", it->first.first, it->first.second,
935 fprintf(fp,
"$EndPhysicalNames\n");
941 fprintf(fp,
"$ParametricNodes\n");
943 fprintf(fp,
"$Nodes\n");
946 fprintf(fp,
"$NOD\n");
948 fprintf(fp,
"%d\n", numVertices);
950 std::vector<GEntity *> entities;
952 for(std::size_t i = 0; i < entities.size(); i++)
953 for(std::size_t j = 0; j < entities[i]->mesh_vertices.size(); j++)
954 entities[i]->mesh_vertices[j]->writeMSH2(fp, binary, saveParametric,
957 if(binary) fprintf(fp,
"\n");
961 fprintf(fp,
"$EndParametricNodes\n");
963 fprintf(fp,
"$EndNodes\n");
964 fprintf(fp,
"$Elements\n");
967 fprintf(fp,
"$ENDNOD\n");
968 fprintf(fp,
"$ELM\n");
971 fprintf(fp,
"%d\n", numElements);
972 int num = elementStartNum;
979 for(std::size_t i = 0; i < (*it)->points.size(); i++)
980 if((*it)->points[i]->ownsParent())
986 for(std::size_t i = 0; i < (*it)->lines.size(); i++)
987 if((*it)->lines[i]->ownsParent())
993 for(std::size_t i = 0; i < (*it)->triangles.size(); i++)
994 if((*it)->triangles[i]->ownsParent())
1000 for(std::size_t i = 0; i < (*it)->tetrahedra.size(); i++)
1001 if((*it)->tetrahedra[i]->ownsParent())
1007 for(std::size_t i = 0; i < (*it)->polygons.size(); i++)
1008 if((*it)->polygons[i]->ownsParent())
1014 for(std::size_t i = 0; i < (*it)->polyhedra.size(); i++)
1015 if((*it)->polyhedra[i]->ownsParent())
1023 writeElementsMSH(fp,
this, *it, (*it)->points, saveAll, saveSinglePartition,
1029 writeElementsMSH(fp,
this, *it, (*it)->lines, saveAll, saveSinglePartition,
1036 saveSinglePartition, version, binary, num,
1042 saveSinglePartition, version, binary, num,
1048 saveSinglePartition, version, binary, num,
1054 saveSinglePartition, version, binary, num,
1060 saveSinglePartition, version, binary, num,
1065 writeElementsMSH(fp,
this, *it, (*it)->prisms, saveAll, saveSinglePartition,
1072 saveSinglePartition, version, binary, num,
1078 saveSinglePartition, version, binary, num,
1083 for(std::size_t i = 0; i < (*it)->triangles.size(); i++) {
1091 for(std::size_t i = 0; i < (*it)->polygons.size(); i++) {
1102 for(std::size_t i = 0; i < (*it)->lines.size(); i++) {
1103 MLine *l = (*it)->lines[i];
1112 if(binary) fprintf(fp,
"\n");
1114 if(version >= 2.0) { fprintf(fp,
"$EndElements\n"); }
1116 fprintf(fp,
"$ENDELM\n");
1127 bool saveAll,
bool saveParametric,
1128 double scalingFactor)
1132 for(std::size_t partition = 1; partition <=
getNumPartitions(); partition++) {
1133 std::ostringstream sstream;
1134 sstream << baseName <<
"_" << partition <<
".msh";
1137 Msg::Info(
"Writing partition %d in file '%s'", partition,
1138 sstream.str().c_str());
1139 _writeMSH2(sstream.str(), 2.2, binary, saveAll, saveParametric,
1140 scalingFactor, startNum, partition,
false,
1142 startNum += numElements;
1147 Msg::Info(
"Writing ghost cells in debug file 'ghosts.pos'");
1148 FILE *fp =
Fopen(
"ghosts.pos",
"w");
1149 fprintf(fp,
"View \"ghosts\"{\n");
1151 it->first->writePOS(fp,
false,
true,
false,
false,
false,
false);
1152 fprintf(fp,
"};\n");