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");