gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
GModelIO_MSH2.cpp
Go to the documentation of this file.
1 // Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 
6 #include <stdlib.h>
7 #include <string.h>
8 #include <map>
9 #include <string>
10 #include <sstream>
11 #include <cassert>
12 #include <iomanip>
13 #include "GModel.h"
14 #include "OS.h"
15 #include "GmshDefines.h"
16 #include "MPoint.h"
17 #include "MLine.h"
18 #include "MTriangle.h"
19 #include "MQuadrangle.h"
20 #include "MTetrahedron.h"
21 #include "MHexahedron.h"
22 #include "MPrism.h"
23 #include "MPyramid.h"
24 #include "MElementCut.h"
25 #include "StringUtils.h"
26 #include "GmshMessage.h"
27 #include "Context.h"
28 #include "OS.h"
29 #include "ghostEdge.h"
30 #include "ghostFace.h"
31 #include "ghostRegion.h"
32 
33 // periodic nodes and entities backported from MSH3 format
34 extern void writeMSHPeriodicNodes(FILE *fp, std::vector<GEntity *> &entities,
35  bool renumber, bool saveAll);
36 extern void readMSHPeriodicNodes(FILE *fp, GModel *gm);
37 extern void writeMSHEntities(FILE *fp, GModel *gm);
38 
39 static bool getMeshVertices(int num, int *indices,
40  std::map<int, MVertex *> &map,
41  std::vector<MVertex *> &vertices)
42 {
43  for(int i = 0; i < num; i++) {
44  if(!map.count(indices[i])) {
45  Msg::Error("Wrong node index %d", indices[i]);
46  return false;
47  }
48  else
49  vertices.push_back(map[indices[i]]);
50  }
51  return true;
52 }
53 
54 static bool getMeshVertices(int num, int *indices, std::vector<MVertex *> &vec,
55  std::vector<MVertex *> &vertices, int minVertex = 0)
56 {
57  for(int i = 0; i < num; i++) {
58  if(indices[i] < minVertex ||
59  indices[i] > (int)(vec.size() - 1 + minVertex)) {
60  Msg::Error("Wrong node index %d", indices[i]);
61  return false;
62  }
63  else
64  vertices.push_back(vec[indices[i]]);
65  }
66  return true;
67 }
68 
69 static MElement *
70 createElementMSH2(GModel *m, int num, int typeMSH, int physical, int reg,
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,
75  MElement *d1 = nullptr, MElement *d2 = nullptr)
76 {
77  if(CTX::instance()->mesh.switchElementTags) {
78  int tmp = reg;
79  reg = physical;
80  physical = tmp;
81  }
82 
83  MElementFactory factory;
84  MElement *e = factory.create(typeMSH, v, num, part, owner, 0, parent, d1, d2);
85 
86  if(!e) {
87  Msg::Error("Unknown type of element %d", typeMSH);
88  return nullptr;
89  }
90 
91  int dim = e->getDim();
92  if(physical &&
93  (!physicals[dim].count(reg) || !physicals[dim][reg].count(physical)))
94  physicals[dim][reg][physical] = "unnamed";
95 
96  if(part > m->getNumPartitions()) m->setNumPartitions(part);
97  return e;
98 }
99 
100 int GModel::_readMSH2(const std::string &name)
101 {
102  FILE *fp = Fopen(name.c_str(), "rb");
103  if(!fp) {
104  Msg::Error("Unable to open file '%s'", name.c_str());
105  return 0;
106  }
107 
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;
115  int minVertex = 0;
116  std::size_t oldNumPartitions = getNumPartitions();
117 
118  while(1) {
119  while(str[0] != '$') {
120  if(!fgets(str, sizeof(str), fp) || feof(fp)) break;
121  }
122 
123  if(feof(fp)) break;
124 
125  if(!strncmp(&str[1], "MeshFormat", 10)) {
126  if(!fgets(str, sizeof(str), fp)) {
127  fclose(fp);
128  return 0;
129  }
130  int format, size;
131  if(sscanf(str, "%lf %d %d", &version, &format, &size) != 3) {
132  fclose(fp);
133  return 0;
134  }
135  if(format) {
136  binary = true;
137  Msg::Debug("Mesh is in binary format");
138  int one;
139  if(fread(&one, sizeof(int), 1, fp) != 1) {
140  fclose(fp);
141  return 0;
142  }
143  if(one != 1) {
144  swap = true;
145  Msg::Debug("Swapping bytes from binary file");
146  }
147  }
148  }
149  else if(!strncmp(&str[1], "PhysicalNames", 13)) {
150  if(!fgets(str, sizeof(str), fp)) {
151  fclose(fp);
152  return 0;
153  }
154  int numNames;
155  if(sscanf(str, "%d", &numNames) != 1) {
156  fclose(fp);
157  return 0;
158  }
159  for(int i = 0; i < numNames; i++) {
160  int dim = -1, num;
161  if(version > 2.0) {
162  if(fscanf(fp, "%d", &dim) != 1) {
163  fclose(fp);
164  return 0;
165  }
166  }
167  if(fscanf(fp, "%d", &num) != 1) {
168  fclose(fp);
169  return 0;
170  }
171  if(!fgets(str, sizeof(str), fp)) {
172  fclose(fp);
173  return 0;
174  }
175  std::string name = ExtractDoubleQuotedString(str, 256);
176  if(name.size()) setPhysicalName(name, dim, num);
177  }
178  }
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)) {
183  fclose(fp);
184  return 0;
185  }
186  int numVertices = -1;
187  if(sscanf(str, "%d", &numVertices) != 1) {
188  fclose(fp);
189  return 0;
190  }
191  Msg::Info("%d nodes", numVertices);
192  Msg::StartProgressMeter(numVertices);
193  vertexVector.clear();
194  vertexMap.clear();
195  minVertex = numVertices + 1;
196  int maxVertex = -1;
197  for(int i = 0; i < numVertices; i++) {
198  int num;
199  double xyz[3], uv[2];
200  MVertex *newVertex = nullptr;
201  if(!parametric) {
202  if(!binary) {
203  if(fscanf(fp, "%d %lf %lf %lf", &num, &xyz[0], &xyz[1], &xyz[2]) !=
204  4) {
205  fclose(fp);
206  return 0;
207  }
208  }
209  else {
210  if(fread(&num, sizeof(int), 1, fp) != 1) {
211  fclose(fp);
212  return 0;
213  }
214  if(swap) SwapBytes((char *)&num, sizeof(int), 1);
215  if(fread(xyz, sizeof(double), 3, fp) != 3) {
216  fclose(fp);
217  return 0;
218  }
219  if(swap) SwapBytes((char *)xyz, sizeof(double), 3);
220  }
221  newVertex = new MVertex(xyz[0], xyz[1], xyz[2], nullptr, num);
222  }
223  else {
224  int iClasDim, iClasTag;
225  if(!binary) {
226  if(fscanf(fp, "%d %lf %lf %lf %d %d", &num, &xyz[0], &xyz[1],
227  &xyz[2], &iClasDim, &iClasTag) != 6) {
228  fclose(fp);
229  return 0;
230  }
231  }
232  else {
233  if(fread(&num, sizeof(int), 1, fp) != 1) {
234  fclose(fp);
235  return 0;
236  }
237  if(swap) SwapBytes((char *)&num, sizeof(int), 1);
238  if(fread(xyz, sizeof(double), 3, fp) != 3) {
239  fclose(fp);
240  return 0;
241  }
242  if(swap) SwapBytes((char *)xyz, sizeof(double), 3);
243  if(fread(&iClasDim, sizeof(int), 1, fp) != 1) {
244  fclose(fp);
245  return 0;
246  }
247  if(swap) SwapBytes((char *)&iClasDim, sizeof(int), 1);
248  if(fread(&iClasTag, sizeof(int), 1, fp) != 1) {
249  fclose(fp);
250  return 0;
251  }
252  if(swap) SwapBytes((char *)&iClasTag, sizeof(int), 1);
253  }
254  if(iClasDim == 0) {
255  GVertex *gv = getVertexByTag(iClasTag);
256  if(gv) gv->mesh_vertices.clear();
257  newVertex = new MVertex(xyz[0], xyz[1], xyz[2], gv, num);
258  }
259  else if(iClasDim == 1) {
260  GEdge *ge = getEdgeByTag(iClasTag);
261  if(!binary) {
262  if(fscanf(fp, "%lf", &uv[0]) != 1) {
263  fclose(fp);
264  return 0;
265  }
266  }
267  else {
268  if(fread(uv, sizeof(double), 1, fp) != 1) {
269  fclose(fp);
270  return 0;
271  }
272  if(swap) SwapBytes((char *)uv, sizeof(double), 1);
273  }
274  newVertex = new MEdgeVertex(xyz[0], xyz[1], xyz[2], ge, uv[0], num);
275  }
276  else if(iClasDim == 2) {
277  GFace *gf = getFaceByTag(iClasTag);
278  if(!binary) {
279  if(fscanf(fp, "%lf %lf", &uv[0], &uv[1]) != 2) {
280  fclose(fp);
281  return 0;
282  }
283  }
284  else {
285  if(fread(uv, sizeof(double), 2, fp) != 2) {
286  fclose(fp);
287  return 0;
288  }
289  if(swap) SwapBytes((char *)uv, sizeof(double), 2);
290  }
291  newVertex =
292  new MFaceVertex(xyz[0], xyz[1], xyz[2], gf, uv[0], uv[1], num);
293  }
294  else if(iClasDim == 3) {
295  GRegion *gr = getRegionByTag(iClasTag);
296  newVertex = new MVertex(xyz[0], xyz[1], xyz[2], gr, num);
297  }
298  }
299  minVertex = std::min(minVertex, num);
300  maxVertex = std::max(maxVertex, num);
301  if(vertexMap.count(num))
302  Msg::Warning("Skipping duplicate node %d", num);
303  vertexMap[num] = newVertex;
304  if(numVertices > 100000)
305  Msg::ProgressMeter(i + 1, true, "Reading nodes");
306  }
308  // If the vertex numbering is dense, transfer the map into a
309  // vector to speed up element creation
310  if((int)vertexMap.size() == numVertices &&
311  ((minVertex == 1 && maxVertex == numVertices) ||
312  (minVertex == 0 && maxVertex == numVertices - 1))) {
313  Msg::Debug("Vertex numbering is dense");
314  vertexVector.resize(vertexMap.size() + 1);
315  if(minVertex == 1)
316  vertexVector[0] = nullptr;
317  else
318  vertexVector[numVertices] = nullptr;
319  for(auto it = vertexMap.begin(); it != vertexMap.end(); ++it)
320  vertexVector[it->first] = it->second;
321  vertexMap.clear();
322  }
323  }
324  else if(!strncmp(&str[1], "ELM", 3) || !strncmp(&str[1], "Elements", 8)) {
325  if(!fgets(str, sizeof(str), fp)) {
326  fclose(fp);
327  return 0;
328  }
329  int numElements;
330 
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;
336 
337  std::set<MElement *> parentsOwned;
338  sscanf(str, "%d", &numElements);
339  Msg::Info("%d elements", numElements);
340  Msg::StartProgressMeter(numElements);
341  if(!binary) {
342  for(int i = 0; i < numElements; i++) {
343  int num, type, physical = 0, elementary = 0, partition = 0,
344  parent = 0;
345  int dom1 = 0, dom2 = 0, numVertices;
346  std::vector<short> ghosts;
347  if(version <= 1.0) {
348  if(fscanf(fp, "%d %d %d %d %d", &num, &type, &physical, &elementary,
349  &numVertices) != 5) {
350  fclose(fp);
351  return 0;
352  }
353  if(numVertices != (int)MElement::getInfoMSH(type)) {
354  fclose(fp);
355  return 0;
356  }
357  }
358  else {
359  int numTags;
360  if(fscanf(fp, "%d %d %d", &num, &type, &numTags) != 3) {
361  fclose(fp);
362  return 0;
363  }
364  int numPartitions = 0;
365  for(int j = 0; j < numTags; j++) {
366  int tag;
367  if(fscanf(fp, "%d", &tag) != 1) {
368  fclose(fp);
369  return 0;
370  }
371  if(j == 0)
372  physical = tag;
373  else if(j == 1)
374  elementary = tag;
375  else if(version < 2.2 && j == 2)
376  partition = tag;
377  else if(version >= 2.2 && j == 2 && numTags > 3)
378  numPartitions = tag;
379  else if(version >= 2.2 && j == 3)
380  partition = tag;
381  else if(j >= 4 && j < 4 + numPartitions - 1)
382  ghosts.push_back(-tag);
383  else if(j == 3 + numPartitions && (numTags == 4 + numPartitions))
384  parent = tag;
385  else if(j == 3 + numPartitions &&
386  (numTags == 5 + numPartitions)) {
387  dom1 = tag;
388  j++;
389  if(fscanf(fp, "%d", &dom2) != 1) {
390  fclose(fp);
391  return 0;
392  }
393  }
394  }
395  if(!(numVertices = MElement::getInfoMSH(type))) {
396  if(type != MSH_POLYG_ && type != MSH_POLYH_ &&
397  type != MSH_POLYG_B) {
398  fclose(fp);
399  return 0;
400  }
401  if(fscanf(fp, "%d", &numVertices) != 1) {
402  fclose(fp);
403  return 0;
404  }
405  }
406  }
407  int *indices = new int[numVertices];
408  for(int j = 0; j < numVertices; j++) {
409  if(fscanf(fp, "%d", &indices[j]) != 1) {
410  delete[] indices;
411  fclose(fp);
412  return 0;
413  }
414  }
415  std::vector<MVertex *> vertices;
416  if(vertexVector.size()) {
417  if(!getMeshVertices(numVertices, indices, vertexVector, vertices,
418  minVertex)) {
419  delete[] indices;
420  fclose(fp);
421  return 0;
422  }
423  }
424  else {
425  if(!getMeshVertices(numVertices, indices, vertexMap, vertices)) {
426  delete[] indices;
427  fclose(fp);
428  return 0;
429  }
430  }
431  MElement *p = nullptr;
432  bool own = false;
433 
434  // search parent element
435  if(parent != 0) {
436  auto ite = elems.find(parent);
437  if(ite == elems.end())
438  Msg::Error(
439  "Parent element (ascii) %d not found for element %d of type %d",
440  parent, num, type);
441  else {
442  p = ite->second;
443  parents[parent] = p;
444  }
445  auto itpo = parentsOwned.find(p);
446  if(itpo == parentsOwned.end()) {
447  own = true;
448  parentsOwned.insert(p);
449  }
450  assert(p != nullptr);
451  }
452 
453  // search domains
454  MElement *doms[2] = {nullptr, nullptr};
455  if(dom1) {
456  auto ite = elems.find(dom1);
457  if(ite == elems.end())
458  Msg::Error("Domain element %d not found for element %d", dom1,
459  num);
460  else
461  doms[0] = ite->second;
462 
463  ite = elems.find(dom2);
464  if(ite != elems.end()) doms[1] = ite->second;
465 
466  if(!doms[0])
467  Msg::Error("Domain element %d not found for element %d", dom1,
468  num);
469  if(dom2 && !doms[1])
470  Msg::Error("Domain element %d not found for element %d", dom2,
471  num);
472  }
473  delete[] indices;
474 
475  if(elementary < 0) continue;
476  MElement *e = createElementMSH2(this, num, type, physical, elementary,
477  partition, vertices, elements,
478  physicals, own, p, doms[0], doms[1]);
479  elems[num] = e;
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)
485  Msg::ProgressMeter(i + 1, true, "Reading elements");
486  }
487  }
488  else {
489  int numElementsPartial = 0;
490  while(numElementsPartial < numElements) {
491  int header[3];
492  if(fread(header, sizeof(int), 3, fp) != 3) {
493  fclose(fp);
494  return 0;
495  }
496  if(swap) SwapBytes((char *)header, sizeof(int), 3);
497  int type = header[0];
498  int numElms = header[1];
499  int numTags = header[2];
500  int numVertices = MElement::getInfoMSH(type);
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) {
505  delete[] data;
506  fclose(fp);
507  return 0;
508  }
509  if(swap) SwapBytes((char *)data, sizeof(int), n);
510  int num = data[0];
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] :
516  0;
517  int parent = (version < 2.2 && numTags > 3) ||
518  (version >= 2.2 && numPartitions &&
519  numTags > 3 + numPartitions) ||
520  (version >= 2.2 && !numPartitions && numTags > 2) ?
521  data[numTags] :
522  0;
523  int *indices = &data[numTags + 1];
524  std::vector<MVertex *> vertices;
525  if(vertexVector.size()) {
526  if(!getMeshVertices(numVertices, indices, vertexVector, vertices,
527  minVertex)) {
528  delete[] data;
529  fclose(fp);
530  return 0;
531  }
532  }
533  else {
534  if(!getMeshVertices(numVertices, indices, vertexMap, vertices)) {
535  delete[] data;
536  fclose(fp);
537  return 0;
538  }
539  }
540  MElement *p = nullptr;
541  bool own = false;
542  if(parent) {
543  auto ite = elems.find(parent);
544  if(ite == elems.end())
545  Msg::Error(
546  "Parent (binary) element %d not found for element %d", parent,
547  num);
548  else {
549  p = ite->second;
550  parents[parent] = p;
551  }
552  auto itpo = parentsOwned.find(p);
553  if(itpo == parentsOwned.end()) {
554  own = true;
555  parentsOwned.insert(p);
556  }
557  assert(p != nullptr);
558  }
559  MElement *e = createElementMSH2(this, num, type, physical,
560  elementary, partition, vertices,
561  elements, physicals, own, p);
562  elems[num] = e;
563  elemreg[num] = elementary;
564  elemphy[num] = physical;
565  if(numPartitions > 1)
566  for(int j = 0; j < numPartitions - 1; j++)
567  _ghostCells.insert(
568  std::pair<MElement *, short>(e, -data[5 + j]));
569  if(numElements > 100000)
570  Msg::ProgressMeter(numElementsPartial + i + 1, true,
571  "Reading elements");
572  }
573  delete[] data;
574  numElementsPartial += numElms;
575  }
576  }
578 
579  for(int i = 0; i < 10; i++) elements[i].clear();
580 
581  for(auto ite = elems.begin(); ite != elems.end(); ite++) {
582  int num = ite->first;
583  MElement *e = ite->second;
584  if(parents.find(num) == parents.end()) {
585  int reg;
586  if(CTX::instance()->mesh.switchElementTags) { reg = elemphy[num]; }
587  else {
588  reg = elemreg[num];
589  }
590  switch(e->getType()) {
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;
601  default:
602  Msg::Error("Wrong type of element");
603  fclose(fp);
604  return 0;
605  }
606  }
607  }
608  }
609  else if(!strncmp(&str[1], "NodeData", 8)) {
610  // there's some nodal post-processing data to read later on, so
611  // cache the vertex indexing data
612  if(vertexVector.size())
613  _vertexVectorCache = vertexVector;
614  else
615  _vertexMapCache = vertexMap;
616  postpro = true;
617  break;
618  }
619  else if(!strncmp(&str[1], "ElementData", 11) ||
620  !strncmp(&str[1], "ElementNodeData", 15)) {
621  // there's some element post-processing data to read later on
622  postpro = true;
623  break;
624  }
625 
626  do {
627  if(!fgets(str, sizeof(str), fp) || feof(fp)) break;
628  } while(str[0] != '$');
629  }
630 
631  // store the elements in their associated elementary entity. If the
632  // entity does not exist, create a new (discrete) one.
633  for(int i = 0; i < (int)(sizeof(elements) / sizeof(elements[0])); i++)
634  _storeElementsInEntities(elements[i]);
635 
636  // associate the correct geometrical entity with each mesh vertex
638 
639  // store the vertices in their associated geometrical entity
640  if(vertexVector.size())
641  _storeVerticesInEntities(vertexVector);
642  else
643  _storeVerticesInEntities(vertexMap);
644 
645  // store the physical tags
646  for(int i = 0; i < 4; i++) _storePhysicalTagsInEntities(i, physicals[i]);
647 
648  // Reading periodic node information is optional in the MSH2 reader, because
649  // the full topology of the model is not stored in MSH2 files. If the full
650  // mesh is not saved (e.g. because only volume mesh elements are saved), some
651  // or all master/slave (lower dimensional) entities will not have been created
652  // when reading the file, which means that no model entities will exist to
653  // store the periodic node information.
654  if(!CTX::instance()->mesh.ignorePeriodicityMsh2) {
655  rewind(fp);
656 
657  while(1) {
658  while(str[0] != '$') {
659  if(!fgets(str, sizeof(str), fp) || feof(fp)) break;
660  }
661  if(feof(fp)) break;
662 
663  if(!strncmp(&str[1], "Periodic", 8) &&
664  strncmp(&str[1], "PeriodicNodes", 13)) {
665  readMSHPeriodicNodes(fp, this);
666  break;
667  }
668  do {
669  if(!fgets(str, sizeof(str), fp) || feof(fp)) break;
670  } while(str[0] != '$');
671  }
672  }
673 
674  fclose(fp);
675 
676  // this post-processing step for periodic boundaries should be removed from
677  // the MSH2 reader. Until then, we also disable it by default.
678  if(!CTX::instance()->mesh.ignorePeriodicityMsh2) {
680  }
681 
682  // attempt to (re)create the model topology
683  if(CTX::instance()->mesh.createTopologyMsh2) { createTopologyFromMesh(); }
684 
685  // create new partition entities if the mesh is partitioned
686  if(CTX::instance()->mesh.partitionConvertMsh2 &&
687  getNumPartitions() > oldNumPartitions) {
689  }
690 
691  return postpro ? 2 : 1;
692 }
693 
694 template <class T>
695 static void writeElementMSH(FILE *fp, GModel *model, GEntity *ge, T *ele,
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)
699 {
700  if(CTX::instance()->mesh.partitionOldStyleMsh2 && ge->getParentEntity() &&
701  ge->getParentEntity()->dim() > ge->dim())
702  return; // ignore partition boundaries
703 
704  if(CTX::instance()->mesh.partitionOldStyleMsh2 &&
705  (ge->geomType() == GEntity::GhostCurve ||
706  ge->geomType() == GEntity::GhostSurface ||
707  ge->geomType() == GEntity::GhostVolume))
708  return; // ignore ghost entities
709 
710  std::vector<short> ghosts;
711  if(model->getGhostCells().size()) {
712  auto itp = model->getGhostCells().equal_range(ele);
713  for(auto it = itp.first; it != itp.second; it++)
714  ghosts.push_back(it->second);
715  }
716 
717  if(saveAll)
718  ele->writeMSH2(fp, version, binary, ++num, elementary, 0, parentNum,
719  dom1Num, dom2Num, &ghosts);
720  else {
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++;
726  }
727  }
728 
729  model->setMeshElementIndex(ele, num); // should really be a multimap...
730 
731  if(CTX::instance()->mesh.saveTri && ele->getNumChildren())
732  num += ele->getNumChildren() - 1;
733 }
734 
735 template <class T>
736 static void writeElementsMSH(FILE *fp, GModel *model, GEntity *ge,
737  std::vector<T *> &ele, bool saveAll,
738  int saveSinglePartition, double version,
739  bool binary, int &num, int elementary,
740  std::vector<int> &physicals)
741 {
742  if(CTX::instance()->mesh.partitionOldStyleMsh2 && ge->getParentEntity() &&
743  ge->getParentEntity()->dim() > ge->dim())
744  return; // ignore partition boundaries
745 
746  if(CTX::instance()->mesh.partitionOldStyleMsh2 &&
747  (ge->geomType() == GEntity::GhostCurve ||
748  ge->geomType() == GEntity::GhostSurface ||
749  ge->geomType() == GEntity::GhostVolume))
750  return; // ignore ghost entities
751 
752  // Hack to save each partition as a separate physical entity
753  if(saveSinglePartition < 0) {
754  if(ele.empty()) return;
755  int offset = -saveSinglePartition;
756  int maxPhysical = model->getMaxPhysicalNumber(ele[0]->getDim());
757  for(std::size_t i = 0; i < ele.size(); i++) {
758  std::vector<int> newPhysicals;
759  int newElementary = elementary;
760  if(elementary > 0) { // classical entity
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());
765  }
766  else if(elementary < 0) { // partition boundary
767  newPhysicals.push_back((maxPhysical - elementary) * offset);
768  }
769  ele[i]->setPartition(0);
770  writeElementMSH(fp, model, ge, ele[i], saveAll, version, binary, num,
771  newElementary, newPhysicals);
772  }
773  return;
774  }
775 
776  for(std::size_t i = 0; i < ele.size(); i++) {
777  if(saveSinglePartition && ele[i]->getPartition() != saveSinglePartition)
778  continue;
779  if(ele[i]->getDomain(0)) continue;
780  int parentNum = 0;
781  MElement *parent = ele[i]->getParent();
782  if(parent) parentNum = model->getMeshElementIndex(parent);
783  writeElementMSH(fp, model, ge, ele[i], saveAll, version, binary, num,
784  elementary, physicals, parentNum);
785  }
786 }
787 
788 static int getNumElementsMSH(GEntity *ge, bool saveAll, int saveSinglePartition)
789 {
790  if(CTX::instance()->mesh.partitionOldStyleMsh2 && ge->getParentEntity() &&
791  ge->getParentEntity()->dim() > ge->dim())
792  return 0; // ignore partition boundaries
793 
794  if(CTX::instance()->mesh.partitionOldStyleMsh2 &&
795  (ge->geomType() == GEntity::GhostCurve ||
796  ge->geomType() == GEntity::GhostSurface ||
797  ge->geomType() == GEntity::GhostVolume))
798  return 0; // ignore ghost entities
799 
800  int n = 0, p = saveAll ? 1 : ge->physicals.size();
801 
802  if(saveSinglePartition < 0 && ge->tag() < 0) p = 1; // partition boundary
803 
804  if(saveSinglePartition <= 0)
805  n = p * ge->getNumMeshElements();
806  else
807  for(std::size_t i = 0; i < ge->getNumMeshElements(); i++)
808  if(ge->getMeshElement(i)->getPartition() == saveSinglePartition) n += p;
809  return n;
810 }
811 
812 static int getNumElementsMSH(GModel *m, bool saveAll, int saveSinglePartition)
813 {
814  int n = 0;
815  for(auto it = m->firstVertex(); it != m->lastVertex(); ++it) {
816  n += getNumElementsMSH(*it, saveAll, saveSinglePartition);
817  if(!CTX::instance()->mesh.saveTri) {
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());
821  }
822  }
823  for(auto it = m->firstEdge(); it != m->lastEdge(); ++it) {
824  n += getNumElementsMSH(*it, saveAll, saveSinglePartition);
825  if(!CTX::instance()->mesh.saveTri) {
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());
829  }
830  }
831  for(auto it = m->firstFace(); it != m->lastFace(); ++it) {
832  n += getNumElementsMSH(*it, saveAll, saveSinglePartition);
833  if(CTX::instance()->mesh.saveTri) {
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());
837  }
838  }
839  else {
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());
846  }
847  }
848  for(auto it = m->firstRegion(); it != m->lastRegion(); ++it) {
849  n += getNumElementsMSH(*it, saveAll, saveSinglePartition);
850  if(CTX::instance()->mesh.saveTri) {
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());
854  }
855  }
856  else {
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());
863  }
864  n -= (*it)->trihedra.size();
865  }
866  return n;
867 }
868 
869 static int _getElementary(GEntity *ge)
870 {
871  if(CTX::instance()->mesh.partitionOldStyleMsh2 && ge->getParentEntity() &&
872  ge->getParentEntity()->dim() == ge->dim()) {
873  // hack for backward compatibility of partitioned meshes in MSH2 format: use
874  // elementary tag of parent entity if they are of the same dimension
875  // (i.e. if they are not partition boundaries)
876  return ge->getParentEntity()->tag();
877  }
878  else {
879  return ge->tag();
880  }
881 }
882 
883 int GModel::_writeMSH2(const std::string &name, double version, bool binary,
884  bool saveAll, bool saveParametric, double scalingFactor,
885  int elementStartNum, int saveSinglePartition,
886  bool append, bool renumberVertices)
887 {
888  FILE *fp;
889  if(append)
890  fp = Fopen(name.c_str(), binary ? "ab" : "a");
891  else
892  fp = Fopen(name.c_str(), binary ? "wb" : "w");
893  if(!fp) {
894  Msg::Error("Unable to open file '%s'", name.c_str());
895  return 0;
896  }
897 
898  // binary format exists only in version 2
899  if(version > 1 || binary)
900  version = 2.2;
901  else
902  version = 1.0;
903 
904  // if there are no physicals we save all the elements
905  if(noPhysicalGroups()) saveAll = true;
906 
907  // get the number of vertices and index the vertices in a continuous
908  // sequence
909 
910  int numVertices =
911  indexMeshVertices(saveAll, saveSinglePartition, renumberVertices);
912 
913  // get the number of elements we need to save
914  int numElements = getNumElementsMSH(this, saveAll, saveSinglePartition);
915 
916  if(version >= 2.0) {
917  fprintf(fp, "$MeshFormat\n");
918  fprintf(fp, "%g %d %d\n", version, binary ? 1 : 0, (int)sizeof(double));
919  if(binary) {
920  int one = 1;
921  fwrite(&one, sizeof(int), 1, fp);
922  fprintf(fp, "\n");
923  }
924  fprintf(fp, "$EndMeshFormat\n");
925 
926  if(numPhysicalNames()) {
927  fprintf(fp, "$PhysicalNames\n");
928  fprintf(fp, "%d\n", numPhysicalNames());
929  for(auto it = firstPhysicalName(); it != lastPhysicalName(); it++) {
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,
933  name.c_str());
934  }
935  fprintf(fp, "$EndPhysicalNames\n");
936  }
937 
938  if(CTX::instance()->mesh.saveTopology) writeMSHEntities(fp, this);
939 
940  if(saveParametric)
941  fprintf(fp, "$ParametricNodes\n");
942  else
943  fprintf(fp, "$Nodes\n");
944  }
945  else
946  fprintf(fp, "$NOD\n");
947 
948  fprintf(fp, "%d\n", numVertices);
949 
950  std::vector<GEntity *> entities;
951  getEntities(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,
955  scalingFactor);
956 
957  if(binary) fprintf(fp, "\n");
958 
959  if(version >= 2.0) {
960  if(saveParametric)
961  fprintf(fp, "$EndParametricNodes\n");
962  else
963  fprintf(fp, "$EndNodes\n");
964  fprintf(fp, "$Elements\n");
965  }
966  else {
967  fprintf(fp, "$ENDNOD\n");
968  fprintf(fp, "$ELM\n");
969  }
970 
971  fprintf(fp, "%d\n", numElements);
972  int num = elementStartNum;
973 
974  _elementIndexCache.clear();
975 
976  // parents
977  if(!CTX::instance()->mesh.saveTri) {
978  for(auto it = firstVertex(); it != lastVertex(); ++it) {
979  for(std::size_t i = 0; i < (*it)->points.size(); i++)
980  if((*it)->points[i]->ownsParent())
981  writeElementMSH(fp, this, *it, (*it)->points[i]->getParent(), saveAll,
982  version, binary, num, _getElementary(*it),
983  (*it)->physicals);
984  }
985  for(auto it = firstEdge(); it != lastEdge(); ++it) {
986  for(std::size_t i = 0; i < (*it)->lines.size(); i++)
987  if((*it)->lines[i]->ownsParent())
988  writeElementMSH(fp, this, *it, (*it)->lines[i]->getParent(), saveAll,
989  version, binary, num, _getElementary(*it),
990  (*it)->physicals);
991  }
992  for(auto it = firstFace(); it != lastFace(); ++it) {
993  for(std::size_t i = 0; i < (*it)->triangles.size(); i++)
994  if((*it)->triangles[i]->ownsParent())
995  writeElementMSH(fp, this, *it, (*it)->triangles[i]->getParent(),
996  saveAll, version, binary, num, _getElementary(*it),
997  (*it)->physicals);
998  }
999  for(auto it = firstRegion(); it != lastRegion(); ++it) {
1000  for(std::size_t i = 0; i < (*it)->tetrahedra.size(); i++)
1001  if((*it)->tetrahedra[i]->ownsParent())
1002  writeElementMSH(fp, this, *it, (*it)->tetrahedra[i]->getParent(),
1003  saveAll, version, binary, num, _getElementary(*it),
1004  (*it)->physicals);
1005  }
1006  for(auto it = firstFace(); it != lastFace(); ++it) {
1007  for(std::size_t i = 0; i < (*it)->polygons.size(); i++)
1008  if((*it)->polygons[i]->ownsParent())
1009  writeElementMSH(fp, this, *it, (*it)->polygons[i]->getParent(),
1010  saveAll, version, binary, num, _getElementary(*it),
1011  (*it)->physicals);
1012  }
1013  for(auto it = firstRegion(); it != lastRegion(); ++it) {
1014  for(std::size_t i = 0; i < (*it)->polyhedra.size(); i++)
1015  if((*it)->polyhedra[i]->ownsParent())
1016  writeElementMSH(fp, this, *it, (*it)->polyhedra[i]->getParent(),
1017  saveAll, version, binary, num, _getElementary(*it),
1018  (*it)->physicals);
1019  }
1020  }
1021  // points
1022  for(auto it = firstVertex(); it != lastVertex(); ++it) {
1023  writeElementsMSH(fp, this, *it, (*it)->points, saveAll, saveSinglePartition,
1024  version, binary, num, _getElementary(*it),
1025  (*it)->physicals);
1026  }
1027  // lines
1028  for(auto it = firstEdge(); it != lastEdge(); ++it) {
1029  writeElementsMSH(fp, this, *it, (*it)->lines, saveAll, saveSinglePartition,
1030  version, binary, num, _getElementary(*it),
1031  (*it)->physicals);
1032  }
1033  // triangles
1034  for(auto it = firstFace(); it != lastFace(); ++it) {
1035  writeElementsMSH(fp, this, *it, (*it)->triangles, saveAll,
1036  saveSinglePartition, version, binary, num,
1037  _getElementary(*it), (*it)->physicals);
1038  }
1039  // quads
1040  for(auto it = firstFace(); it != lastFace(); ++it) {
1041  writeElementsMSH(fp, this, *it, (*it)->quadrangles, saveAll,
1042  saveSinglePartition, version, binary, num,
1043  _getElementary(*it), (*it)->physicals);
1044  }
1045  // polygons
1046  for(auto it = firstFace(); it != lastFace(); it++) {
1047  writeElementsMSH(fp, this, *it, (*it)->polygons, saveAll,
1048  saveSinglePartition, version, binary, num,
1049  _getElementary(*it), (*it)->physicals);
1050  }
1051  // tets
1052  for(auto it = firstRegion(); it != lastRegion(); ++it) {
1053  writeElementsMSH(fp, this, *it, (*it)->tetrahedra, saveAll,
1054  saveSinglePartition, version, binary, num,
1055  _getElementary(*it), (*it)->physicals);
1056  }
1057  // hexas
1058  for(auto it = firstRegion(); it != lastRegion(); ++it) {
1059  writeElementsMSH(fp, this, *it, (*it)->hexahedra, saveAll,
1060  saveSinglePartition, version, binary, num,
1061  _getElementary(*it), (*it)->physicals);
1062  }
1063  // prisms
1064  for(auto it = firstRegion(); it != lastRegion(); ++it) {
1065  writeElementsMSH(fp, this, *it, (*it)->prisms, saveAll, saveSinglePartition,
1066  version, binary, num, _getElementary(*it),
1067  (*it)->physicals);
1068  }
1069  // pyramids
1070  for(auto it = firstRegion(); it != lastRegion(); ++it) {
1071  writeElementsMSH(fp, this, *it, (*it)->pyramids, saveAll,
1072  saveSinglePartition, version, binary, num,
1073  _getElementary(*it), (*it)->physicals);
1074  }
1075  // polyhedra
1076  for(auto it = firstRegion(); it != lastRegion(); ++it) {
1077  writeElementsMSH(fp, this, *it, (*it)->polyhedra, saveAll,
1078  saveSinglePartition, version, binary, num,
1079  _getElementary(*it), (*it)->physicals);
1080  }
1081  // level set faces
1082  for(auto it = firstFace(); it != lastFace(); ++it) {
1083  for(std::size_t i = 0; i < (*it)->triangles.size(); i++) {
1084  MTriangle *t = (*it)->triangles[i];
1085  if(t->getDomain(0))
1086  writeElementMSH(fp, this, *it, t, saveAll, version, binary, num,
1087  _getElementary(*it), (*it)->physicals, 0,
1090  }
1091  for(std::size_t i = 0; i < (*it)->polygons.size(); i++) {
1092  MPolygon *p = (*it)->polygons[i];
1093  if(p->getDomain(0))
1094  writeElementMSH(fp, this, *it, p, saveAll, version, binary, num,
1095  _getElementary(*it), (*it)->physicals, 0,
1098  }
1099  }
1100  // level set lines
1101  for(auto it = firstEdge(); it != lastEdge(); ++it) {
1102  for(std::size_t i = 0; i < (*it)->lines.size(); i++) {
1103  MLine *l = (*it)->lines[i];
1104  if(l->getDomain(0))
1105  writeElementMSH(fp, this, *it, l, saveAll, version, binary, num,
1106  _getElementary(*it), (*it)->physicals, 0,
1109  }
1110  }
1111 
1112  if(binary) fprintf(fp, "\n");
1113 
1114  if(version >= 2.0) { fprintf(fp, "$EndElements\n"); }
1115  else {
1116  fprintf(fp, "$ENDELM\n");
1117  }
1118 
1119  writeMSHPeriodicNodes(fp, entities, renumberVertices, saveAll);
1120 
1121  fclose(fp);
1122 
1123  return 1;
1124 }
1125 
1126 int GModel::_writePartitionedMSH2(const std::string &baseName, bool binary,
1127  bool saveAll, bool saveParametric,
1128  double scalingFactor)
1129 {
1130  int numElements;
1131  int startNum = 0;
1132  for(std::size_t partition = 1; partition <= getNumPartitions(); partition++) {
1133  std::ostringstream sstream;
1134  sstream << baseName << "_" << partition << ".msh";
1135 
1136  numElements = getNumElementsMSH(this, saveAll, partition);
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,
1141  false); // NO RENUMBERING!
1142  startNum += numElements; // update for next iteration in the loop
1143  }
1144 
1145 #if 0
1146  if(_ghostCells.size()){
1147  Msg::Info("Writing ghost cells in debug file 'ghosts.pos'");
1148  FILE *fp = Fopen("ghosts.pos", "w");
1149  fprintf(fp, "View \"ghosts\"{\n");
1150  for(auto it = _ghostCells.begin(); it != _ghostCells.end(); it++)
1151  it->first->writePOS(fp, false, true, false, false, false, false);
1152  fprintf(fp, "};\n");
1153  fclose(fp);
1154  }
1155 #endif
1156 
1157  return 1;
1158 }
MTriangle.h
GModel::getGhostCells
std::multimap< MElement *, short > & getGhostCells()
Definition: GModel.h:618
GModel::firstEdge
eiter firstEdge()
Definition: GModel.h:356
GEntity::GhostCurve
@ GhostCurve
Definition: GEntity.h:125
MElement::getDomain
virtual MElement * getDomain(int i) const
Definition: MElement.h:243
GModel::convertOldPartitioningToNewOne
int convertOldPartitioningToNewOne()
Definition: GModel.cpp:2236
TYPE_LIN
#define TYPE_LIN
Definition: GmshDefines.h:65
GFace
Definition: GFace.h:33
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
MElementFactory
Definition: MElement.h:517
ghostFace.h
OS.h
getMeshVertices
static bool getMeshVertices(int num, int *indices, std::map< int, MVertex * > &map, std::vector< MVertex * > &vertices)
Definition: GModelIO_MSH2.cpp:39
Msg::Debug
static void Debug(const char *fmt,...)
Definition: GmshMessage.cpp:752
MVertex
Definition: MVertex.h:24
MElement::getDim
virtual int getDim() const =0
GEntity::getParentEntity
virtual GEntity * getParentEntity()
Definition: GEntity.h:199
GModel::numPhysicalNames
int numPhysicalNames() const
Definition: GModel.h:464
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
GEntity::physicals
std::vector< int > physicals
Definition: GEntity.h:65
MElement::getParent
virtual MElement * getParent() const
Definition: MElement.h:231
GModel::getFaceByTag
GFace * getFaceByTag(int n) const
Definition: GModel.cpp:326
TYPE_PNT
#define TYPE_PNT
Definition: GmshDefines.h:64
GModel::_storeElementsInEntities
void _storeElementsInEntities(std::map< int, std::vector< MElement * > > &map)
Definition: GModel.cpp:2273
GModel::_readMSH2
int _readMSH2(const std::string &name)
Definition: GModelIO_MSH2.cpp:100
TYPE_TRI
#define TYPE_TRI
Definition: GmshDefines.h:66
writeMSHPeriodicNodes
void writeMSHPeriodicNodes(FILE *fp, std::vector< GEntity * > &entities, bool renumber, bool saveAll)
Definition: GModelIO_MSH3.cpp:674
MPoint.h
GModel::firstVertex
viter firstVertex()
Definition: GModel.h:357
GModel::getEdgeByTag
GEdge * getEdgeByTag(int n) const
Definition: GModel.cpp:336
GmshMessage.h
MLine.h
GEntity
Definition: GEntity.h:31
GModel::firstPhysicalName
piter firstPhysicalName()
Definition: GModel.h:458
TYPE_PRI
#define TYPE_PRI
Definition: GmshDefines.h:70
_getElementary
static int _getElementary(GEntity *ge)
Definition: GModelIO_MSH2.cpp:869
GModel::getNumPartitions
std::size_t getNumPartitions() const
Definition: GModel.h:602
GModel::setNumPartitions
void setNumPartitions(std::size_t npart)
Definition: GModel.h:603
GEntity::GhostSurface
@ GhostSurface
Definition: GEntity.h:126
GModel::getMeshElementIndex
int getMeshElementIndex(MElement *e)
Definition: GModel.cpp:2027
Fopen
FILE * Fopen(const char *f, const char *mode)
Definition: OS.cpp:273
GModel::_elementIndexCache
std::map< int, int > _elementIndexCache
Definition: GModel.h:105
MLine
Definition: MLine.h:21
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
GModel::lastFace
fiter lastFace()
Definition: GModel.h:359
SwapBytes
void SwapBytes(char *array, int size, int n)
Definition: StringUtils.cpp:16
GEntity::mesh_vertices
std::vector< MVertex * > mesh_vertices
Definition: GEntity.h:56
MElement::getType
virtual int getType() const =0
MElementCut.h
MHexahedron.h
MEdgeVertex
Definition: MVertex.h:137
GModel::lastVertex
viter lastVertex()
Definition: GModel.h:361
GEntity::getNumMeshElements
virtual std::size_t getNumMeshElements() const
Definition: GEntity.h:348
GVertex
Definition: GVertex.h:23
GModel::getMaxPhysicalNumber
int getMaxPhysicalNumber(int dim)
Definition: GModel.cpp:917
swap
void swap(double &a, double &b)
Definition: meshTriangulation.cpp:27
GModel
Definition: GModel.h:44
Msg::StopProgressMeter
static void StopProgressMeter()
Definition: GmshMessage.cpp:318
GModel::vertices
std::set< GVertex *, GEntityPtrLessThan > vertices
Definition: GModel.h:146
writeElementsMSH
static void writeElementsMSH(FILE *fp, GModel *model, GEntity *ge, std::vector< T * > &ele, bool saveAll, int saveSinglePartition, double version, bool binary, int &num, int elementary, std::vector< int > &physicals)
Definition: GModelIO_MSH2.cpp:736
GModel::createTopologyFromMesh
void createTopologyFromMesh()
Definition: GModelCreateTopologyFromMesh.cpp:663
GModel::_ghostCells
std::multimap< MElement *, short > _ghostCells
Definition: GModel.h:110
MPyramid.h
GEntity::geomType
virtual GeomType geomType() const
Definition: GEntity.h:238
GModel::firstFace
fiter firstFace()
Definition: GModel.h:355
GmshDefines.h
writeElementMSH
static void writeElementMSH(FILE *fp, GModel *model, GEntity *ge, T *ele, bool saveAll, double version, bool binary, int &num, int elementary, std::vector< int > &physicals, int parentNum=0, int dom1Num=0, int dom2Num=0)
Definition: GModelIO_MSH2.cpp:695
MSH_POLYG_B
#define MSH_POLYG_B
Definition: GmshDefines.h:148
createElementMSH2
static MElement * createElementMSH2(GModel *m, int num, int typeMSH, int physical, int reg, unsigned int part, std::vector< MVertex * > &v, std::map< int, std::vector< MElement * > > elements[10], std::map< int, std::map< int, std::string > > physicals[4], bool owner=false, MElement *parent=nullptr, MElement *d1=nullptr, MElement *d2=nullptr)
Definition: GModelIO_MSH2.cpp:70
MElement
Definition: MElement.h:30
ExtractDoubleQuotedString
std::string ExtractDoubleQuotedString(const char *str, int len)
Definition: StringUtils.cpp:27
GEntity::GhostVolume
@ GhostVolume
Definition: GEntity.h:127
GModel::_vertexMapCache
std::map< int, MVertex * > _vertexMapCache
Definition: GModel.h:102
GEntity::tag
int tag() const
Definition: GEntity.h:280
MFaceVertex
Definition: MVertex.h:168
GModel::_writePartitionedMSH2
int _writePartitionedMSH2(const std::string &baseName, bool binary, bool saveAll, bool saveParametric, double scalingFactor)
Definition: GModelIO_MSH2.cpp:1126
GModel::_vertexVectorCache
std::vector< MVertex * > _vertexVectorCache
Definition: GModel.h:101
GModel::getEntities
void getEntities(std::vector< GEntity * > &entities, int dim=-1) const
Definition: GModel.cpp:651
GModel::alignPeriodicBoundaries
void alignPeriodicBoundaries()
Definition: GModel.cpp:2828
GRegion
Definition: GRegion.h:28
MTriangle
Definition: MTriangle.h:26
TYPE_PYR
#define TYPE_PYR
Definition: GmshDefines.h:69
StringUtils.h
MElementFactory::create
MElement * create(int type, std::vector< MVertex * > &v, std::size_t num=0, int part=0, bool owner=false, int parent=0, MElement *parent_ptr=nullptr, MElement *d1=nullptr, MElement *d2=nullptr)
Definition: MElement.cpp:2556
readMSHPeriodicNodes
void readMSHPeriodicNodes(FILE *fp, GModel *gm)
Definition: GModelIO_MSH3.cpp:125
GModel::firstRegion
riter firstRegion()
Definition: GModel.h:354
MSH_POLYH_
#define MSH_POLYH_
Definition: GmshDefines.h:114
TYPE_QUA
#define TYPE_QUA
Definition: GmshDefines.h:67
GModel::lastRegion
riter lastRegion()
Definition: GModel.h:358
TYPE_POLYG
#define TYPE_POLYG
Definition: GmshDefines.h:72
Context.h
GEntity::getMeshElement
virtual MElement * getMeshElement(std::size_t index) const
Definition: GEntity.h:363
MTetrahedron.h
GModel::_writeMSH2
int _writeMSH2(const std::string &name, double version, bool binary, bool saveAll, bool saveParametric, double scalingFactor, int elementStartNum, int saveSinglePartition, bool append, bool renumberVertices)
Definition: GModelIO_MSH2.cpp:883
GModel::lastPhysicalName
piter lastPhysicalName()
Definition: GModel.h:459
MQuadrangle.h
MElement::getInfoMSH
static unsigned int getInfoMSH(const int typeMSH, const char **const name=nullptr)
Definition: MElement.cpp:2057
GModel::setMeshElementIndex
void setMeshElementIndex(MElement *e, int index)
Definition: GModel.cpp:2036
MSH_POLYG_
#define MSH_POLYG_
Definition: GmshDefines.h:113
GModel::noPhysicalGroups
bool noPhysicalGroups()
Definition: GModel.cpp:828
Msg::StartProgressMeter
static void StartProgressMeter(int ntotal)
Definition: GmshMessage.cpp:312
GEdge
Definition: GEdge.h:26
TYPE_HEX
#define TYPE_HEX
Definition: GmshDefines.h:71
MPrism.h
TYPE_TET
#define TYPE_TET
Definition: GmshDefines.h:68
GModel::setPhysicalName
int setPhysicalName(const std::string &name, int dim, int num=0)
Definition: GModel.cpp:937
writeMSHEntities
void writeMSHEntities(FILE *fp, GModel *gm)
Definition: GModelIO_MSH3.cpp:574
GModel::mesh
int mesh(int dimension)
Definition: GModel.cpp:1066
getNumElementsMSH
static int getNumElementsMSH(GEntity *ge, bool saveAll, int saveSinglePartition)
Definition: GModelIO_MSH2.cpp:788
GModel::lastEdge
eiter lastEdge()
Definition: GModel.h:360
MPolygon
Definition: MElementCut.h:198
GModel.h
ghostEdge.h
GModel::getRegionByTag
GRegion * getRegionByTag(int n) const
Definition: GModel.cpp:316
GModel::_storeVerticesInEntities
void _storeVerticesInEntities(std::map< int, MVertex * > &vertices)
Definition: GModel.cpp:2496
MElement::getPartition
virtual int getPartition() const
Definition: MElement.h:92
GEntity::dim
virtual int dim() const
Definition: GEntity.h:196
Msg::ProgressMeter
static void ProgressMeter(int n, bool log, const char *fmt,...)
Definition: GmshMessage.cpp:783
GModel::getVertexByTag
GVertex * getVertexByTag(int n) const
Definition: GModel.cpp:346
ghostRegion.h
GModel::_associateEntityWithMeshVertices
void _associateEntityWithMeshVertices()
Definition: GModel.cpp:2470
TYPE_POLYH
#define TYPE_POLYH
Definition: GmshDefines.h:73
GModel::indexMeshVertices
std::size_t indexMeshVertices(bool all, int singlePartition=0, bool renumber=true)
Definition: GModel.cpp:2135
GModel::_storePhysicalTagsInEntities
void _storePhysicalTagsInEntities(int dim, std::map< int, std::map< int, std::string > > &map)
Definition: GModel.cpp:2568