32 if(fscanf(fp,
"%d", &nump) != 1)
return 0;
33 for(
int i = 0; i < nump; i++) {
35 if(fscanf(fp,
"%d", &tag) != 1)
return 0;
45 if(fscanf(fp,
"%d %d %d %d", &nv, &ne, &nf, &nr) != 4)
return;
46 for(
int i = 0; i < nv; i++) {
47 if(fscanf(fp,
"%d", &tag) != 1)
return;
55 for(
int i = 0; i < ne; i++) {
57 if(fscanf(fp,
"%d %d", &tag, &n) != 2)
return;
60 GVertex *v1 =
nullptr, *v2 =
nullptr;
61 for(
int j = 0; j < n; j++) {
63 if(fscanf(fp,
"%d", &tagv) != 1) {
77 for(
int i = 0; i < nf; i++) {
79 if(fscanf(fp,
"%d %d", &tag, &n) != 2)
return;
83 std::vector<int>
edges, signs;
84 for(
int j = 0; j < n; j++) {
86 if(fscanf(fp,
"%d", &tage) != 1) {
90 edges.push_back(std::abs(tage));
91 int sign = tage > 0 ? 1 : -1;
92 signs.push_back(sign);
94 df->setBoundEdges(
edges, signs);
100 for(
int i = 0; i < nr; i++) {
102 if(fscanf(fp,
"%d %d", &tag, &n) != 2)
return;
106 std::vector<int>
faces, signs;
107 for(
int j = 0; j < n; j++) {
109 if(fscanf(fp,
"%d", &tagf) != 1) {
113 faces.push_back(std::abs(tagf));
114 int sign = tagf > 0 ? 1 : -1;
115 signs.push_back(sign);
128 if(fscanf(fp,
"%d", &count) != 1)
return;
129 for(
int i = 0; i < count; i++) {
130 int dim, slave, master;
132 if(fscanf(fp,
"%d %d %d", &dim, &slave, &master) != 3)
continue;
134 GEntity *s =
nullptr, *m =
nullptr;
153 bool completePer = s && m;
158 if(fscanf(fp,
"%s", token) != 1)
return;
159 if(strcmp(token,
"Affine") == 0) {
160 std::vector<double> tfo(16);
161 for(
int i = 0; i < 16; i++) {
162 if(fscanf(fp,
"%lf", &tfo[i]) != 1)
return;
171 if(fscanf(fp,
"%d", &numv) != 1) numv = 0;
172 for(
int j = 0; j < numv; j++) {
174 if(fscanf(fp,
"%d %d", &v1, &v2) != 2)
continue;
181 Msg::Info(
"Could not find periodic slave entity %d of dimension %d",
184 Msg::Info(
"Could not find periodic master entity %d of dimension %d",
192 FILE *fp =
Fopen(name.c_str(),
"rb");
194 Msg::Error(
"Unable to open file '%s'", name.c_str());
200 bool binary =
false,
swap =
false, postpro =
false;
202 std::map<int, std::vector<MElement *> > elements[11];
206 while(str[0] !=
'$') {
207 if(!fgets(str,
sizeof(str), fp) || feof(fp))
break;
213 if(!strncmp(&str[1],
"MeshFormat", 10)) {
214 if(!fgets(str,
sizeof(str), fp)) {
219 if(sscanf(str,
"%lf %d %d", &version, &format, &size) != 3) {
223 if(version < 3. || version >= 4.) {
224 Msg::Error(
"Wrong MSH file version %g for MSH3 reader", version);
232 if(fread(&one,
sizeof(
int), 1, fp) != 1) {
238 Msg::Debug(
"Swapping bytes from binary file");
244 else if(!strncmp(&str[1],
"PhysicalNames", 13)) {
245 if(!fgets(str,
sizeof(str), fp)) {
250 if(sscanf(str,
"%d", &numNames) != 1) {
254 for(
int i = 0; i < numNames; i++) {
256 if(fscanf(fp,
"%d", &dim) != 1) {
260 if(fscanf(fp,
"%d", &num) != 1) {
264 if(!fgets(str,
sizeof(str), fp)) {
274 else if(!strncmp(&str[1],
"Entities", 8)) {
279 else if(!strncmp(&str[1],
"Nodes", 5)) {
280 if(!fgets(str,
sizeof(str), fp)) {
285 if(sscanf(str,
"%d", &numVertices) != 1) {
294 minVertex = numVertices + 1;
295 for(
int i = 0; i < numVertices; i++) {
296 int num, entity, dim;
300 if(fscanf(fp,
"%d %lf %lf %lf %d", &num, &xyz[0], &xyz[1], &xyz[2],
307 if(fread(&num,
sizeof(
int), 1, fp) != 1) {
312 if(fread(xyz,
sizeof(
double), 3, fp) != 3) {
317 if(fread(&entity,
sizeof(
int), 1, fp) != 1) {
324 vertex =
new MVertex(xyz[0], xyz[1], xyz[2],
nullptr, num);
328 if(fscanf(fp,
"%d", &dim) != 1) {
334 if(fread(&dim,
sizeof(
int), 1, fp) != 1) {
345 vertex =
new MVertex(xyz[0], xyz[1], xyz[2], gv, num);
351 if(fscanf(fp,
"%lf", &u) != 1) {
357 if(fread(&u,
sizeof(
double), 1, fp) != 1) {
363 vertex =
new MEdgeVertex(xyz[0], xyz[1], xyz[2], ge, u, num);
369 if(fscanf(fp,
"%lf %lf", &uv[0], &uv[1]) != 2) {
375 if(fread(uv,
sizeof(
double), 2, fp) != 2) {
382 new MFaceVertex(xyz[0], xyz[1], xyz[2], gf, uv[0], uv[1], num);
388 if(fscanf(fp,
"%lf %lf %lf", &uvw[0], &uvw[1], &uvw[2]) != 3) {
394 if(fread(uvw,
sizeof(
double), 3, fp) != 3) {
400 vertex =
new MVertex(xyz[0], xyz[1], xyz[2], gr, num);
403 Msg::Error(
"Wrong entity dimension for node %d", num);
408 minVertex = std::min(minVertex, num);
409 maxVertex = std::max(maxVertex, num);
413 if(numVertices > 100000)
420 ((minVertex == 1 && maxVertex == numVertices) ||
421 (minVertex == 0 && maxVertex == numVertices - 1))) {
435 else if(!strncmp(&str[1],
"Elements", 8)) {
436 if(!fgets(str,
sizeof(str), fp)) {
441 if(sscanf(str,
"%d", &numElements) != 1) {
447 for(
int i = 0; i < numElements; i++) {
448 int num, type, entity, numData;
450 if(fscanf(fp,
"%d %d %d %d", &num, &type, &entity, &numData) != 4) {
456 if(fread(&num,
sizeof(
int), 1, fp) != 1) {
461 if(fread(&type,
sizeof(
int), 1, fp) != 1) {
466 if(fread(&entity,
sizeof(
int), 1, fp) != 1) {
471 if(fread(&numData,
sizeof(
int), 1, fp) != 1) {
477 std::vector<int> data;
479 data.resize(numData);
481 for(
int j = 0; j < numData; j++) {
482 if(fscanf(fp,
"%d", &data[j]) != 1) {
489 if((
int)fread(&data[0],
sizeof(
int), numData, fp) != numData) {
515 if(numElements > 100000)
522 else if(!strncmp(&str[1],
"Periodic", 8)) {
527 else if(!strncmp(&str[1],
"NodeData", 8) ||
528 !strncmp(&str[1],
"ElementData", 11) ||
529 !strncmp(&str[1],
"ElementNodeData", 15)) {
535 if(!fgets(str,
sizeof(str), fp) || feof(fp))
break;
536 }
while(str[0] !=
'$');
541 for(
int i = 0; i < (int)(
sizeof(elements) /
sizeof(elements[0])); i++)
553 for(
int i = 0; i < (int)(
sizeof(elements) /
sizeof(elements[0])); i++)
563 return postpro ? 2 : 1;
569 fprintf(fp,
"%d ", (
int)phys.size());
570 for(
auto itp = phys.begin(); itp != phys.end(); itp++)
571 fprintf(fp,
"%d ", *itp);
576 fprintf(fp,
"$Entities\n");
580 fprintf(fp,
"%d ", (*it)->tag());
585 std::list<GVertex *> vertices;
586 if((*it)->getBeginVertex()) vertices.push_back((*it)->getBeginVertex());
587 if((*it)->getEndVertex()) vertices.push_back((*it)->getEndVertex());
588 fprintf(fp,
"%d %d ", (*it)->tag(), (
int)vertices.size());
589 for(
auto itv = vertices.begin(); itv != vertices.end(); itv++) {
590 fprintf(fp,
"%d ", (*itv)->tag());
596 std::vector<GEdge *>
const &
edges = (*it)->edges();
597 std::vector<int>
const &ori = (*it)->edgeOrientations();
598 fprintf(fp,
"%d %d ", (*it)->tag(), (
int)
edges.size());
599 std::vector<int>
tags;
600 for(
auto ite =
edges.begin(); ite !=
edges.end(); ite++)
601 tags.push_back((*ite)->tag());
603 std::vector<int> signs(ori.begin(), ori.end());
605 if(
tags.size() == signs.size()) {
606 for(std::size_t i = 0; i <
tags.size(); i++)
607 tags[i] *= (signs[i] > 0 ? 1 : -1);
609 for(std::size_t i = 0; i <
tags.size(); i++) fprintf(fp,
"%d ",
tags[i]);
614 std::vector<GFace *>
faces = (*it)->faces();
615 std::vector<int> ori = (*it)->faceOrientations();
616 fprintf(fp,
"%d %d ", (*it)->tag(), (
int)
faces.size());
617 std::vector<int>
tags, signs;
618 for(
auto itf =
faces.begin(); itf !=
faces.end(); itf++)
619 tags.push_back((*itf)->tag());
620 for(
auto itf = ori.begin(); itf != ori.end(); itf++)
621 signs.push_back(*itf);
622 if(
tags.size() == signs.size()) {
623 for(std::size_t i = 0; i <
tags.size(); i++)
624 tags[i] *= (signs[i] > 0 ? 1 : -1);
626 for(std::size_t i = 0; i <
tags.size(); i++) fprintf(fp,
"%d ",
tags[i]);
630 fprintf(fp,
"$EndEntities\n");
637 if(saveSinglePartition <= 0)
650 std::vector<short> ghosts;
652 for(
auto it = itp.first; it != itp.second; it++)
653 ghosts.push_back(it->second);
654 ele->
writeMSH3(fp, binary, elementary, &ghosts);
662 std::vector<T *> &ele,
bool saveAll,
663 int saveSinglePartition,
bool binary)
666 for(std::size_t i = 0; i < ele.size(); i++) {
667 if(saveSinglePartition && ele[i]->getPartition() != saveSinglePartition)
675 bool renumber,
bool saveAll)
678 for(std::size_t i = 0; i < entities.size(); i++) {
679 if(entities[i]->getMeshMaster() != entities[i] &&
680 (saveAll || (entities[i]->physicals.size() &&
681 entities[i]->getMeshMaster()->physicals.size()))) {
686 fprintf(fp,
"$Periodic\n");
687 fprintf(fp,
"%d\n", count);
688 for(std::size_t i = 0; i < entities.size(); i++) {
689 GEntity *g_slave = entities[i];
691 if(g_slave != g_master &&
692 (saveAll || (entities[i]->physicals.size() &&
693 entities[i]->getMeshMaster()->physicals.size()))) {
694 fprintf(fp,
"%d %d %d\n", g_slave->
dim(), g_slave->
tag(),
698 fprintf(fp,
"Affine");
699 for(
int i = 0; i < 16; i++)
704 std::map<MVertex *, MVertex *, MVertexPtrLessThan> corrVert;
711 fprintf(fp,
"%d\n", (
int)corrVert.size());
712 for(
auto it = corrVert.begin(); it != corrVert.end(); it++) {
722 fprintf(fp,
"$EndPeriodic\n");
726 bool saveAll,
bool saveParametric,
double scalingFactor,
727 int elementStartNum,
int saveSinglePartition,
730 if(version < 3. || version >= 4.) {
731 Msg::Error(
"Wrong MSH file version %g for MSH3 writer", version);
737 fp =
Fopen(name.c_str(), binary ?
"ab" :
"a");
739 fp =
Fopen(name.c_str(), binary ?
"wb" :
"w");
741 Msg::Error(
"Unable to open file '%s'", name.c_str());
747 bool renumber =
false;
757 std::vector<GEntity *> entities;
760 for(std::size_t i = 0; i < entities.size(); i++)
763 fprintf(fp,
"$MeshFormat\n");
764 fprintf(fp,
"%g %d %d\n", version, binary ? 1 : 0, (
int)
sizeof(
double));
767 fwrite(&one,
sizeof(
int), 1, fp);
770 fprintf(fp,
"$EndMeshFormat\n");
773 fprintf(fp,
"$PhysicalNames\n");
776 std::string name = it->second;
777 if(name.size() > 254) name.resize(254);
778 fprintf(fp,
"%d %d \"%s\"\n", it->first.first, it->first.second,
781 fprintf(fp,
"$EndPhysicalNames\n");
786 fprintf(fp,
"$Nodes\n");
787 fprintf(fp,
"%d\n", numVertices);
788 for(std::size_t i = 0; i < entities.size(); i++)
789 for(std::size_t j = 0; j < entities[i]->mesh_vertices.size(); j++)
790 entities[i]->mesh_vertices[j]->
writeMSH(fp, binary, saveParametric,
793 if(binary) fprintf(fp,
"\n");
794 fprintf(fp,
"$EndNodes\n");
796 fprintf(fp,
"$Elements\n");
797 fprintf(fp,
"%d\n", numElements);
803 saveSinglePartition, binary);
806 saveSinglePartition, binary);
808 writeElementsMSH(fp,
this, *it, (*it)->prisms, saveAll, saveSinglePartition,
812 saveSinglePartition, binary);
815 saveSinglePartition, binary);
818 saveSinglePartition, binary);
821 saveSinglePartition, binary);
826 writeElementsMSH(fp,
this, *it, (*it)->points, saveAll, saveSinglePartition,
829 if(binary) fprintf(fp,
"\n");
831 fprintf(fp,
"$EndElements\n");
842 bool binary,
bool saveAll,
843 bool saveParametric,
double scalingFactor)
845 if(version < 3. || version >= 4.) {
846 Msg::Error(
"Wrong MSH file version %g for MSH3 writer", version);
850 for(std::size_t partition = 0; partition <
getNumPartitions(); partition++) {
851 std::ostringstream sstream;
852 sstream << baseName <<
"_" << std::setw(6) << std::setfill(
'0')
854 Msg::Info(
"Writing partition %d in file '%s'", partition,
855 sstream.str().c_str());
856 _writeMSH3(sstream.str(), version, binary, saveAll, saveParametric,
857 scalingFactor, 0, partition,
false);