gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
CGNSWriteStruct.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 
7 #include <math.h>
8 #include <sstream>
9 #include <iomanip>
10 #include "GModel.h"
11 #include "Context.h"
12 #include "CGNSCommon.h"
13 #include "CGNSConventions.h"
14 
15 // The structured CGNS writer follows ICEM-like conventions, which are
16 // significantly different from those used in the unstructured CGNS writer:
17 //
18 // - structured 3D (resp. 2D) meshes contain one zone per volume (resp.
19 // surface) and no zones are created for lower dimensional entities; the
20 // unstructured writer creates a single zone per mesh partition (i.e. a single
21 // zone for non-partitioned meshes)
22 //
23 // - all structured volumes (3D) or surfaces (2D) are saved; if physical groups
24 // are defined, the unstructured writer only saves entities belonging to
25 // physical groups, unless Mesh.SaveAll is set
26 //
27 // - interfaces between structured zones are 1-to-1, with point ranges; the
28 // unstructured writer creates interfaces (between partitions) defined by
29 // point lists
30 //
31 // - elementary entity tags are encoded in the zone name; the unstructured
32 // writer writes elementary entity information as boundary conditions and
33 // family names
34 //
35 // - physical groups for the highest dimensional entities are directly encoded
36 // at the begining of the zone name; the unstructured writer saves physical
37 // names in families
38 //
39 // - boundary conditions are created for all zone boundaries, and if physical
40 // groups are defined on boundaries they are also saved as families
41 
42 #if defined(HAVE_LIBCGNS)
43 
44 static bool isTransfinite(GFace *gf)
45 {
46  return gf->transfinite_vertices.size() && gf->transfinite_vertices[0].size();
47 }
48 
49 static bool isTransfinite(GRegion *gr)
50 {
51  return gr->transfinite_vertices.size() &&
52  gr->transfinite_vertices[0].size() &&
53  gr->transfinite_vertices[0][0].size();
54 }
55 
56 static std::string getDimName(int dim)
57 {
58  switch(dim) {
59  case 0: return "P"; break;
60  case 1: return "C"; break;
61  case 2: return "S"; break;
62  case 3: return "V"; break;
63  }
64  return "";
65 }
66 
67 static std::string getZoneName(GEntity *ge, bool withPhysical = true,
68  bool withElementary = true)
69 {
70  std::ostringstream sstream;
71 
72  if(withPhysical) {
73  for(std::size_t i = 0; i < ge->physicals.size(); i++) {
74  if(i) sstream << " ";
75  int t = std::abs(ge->physicals[i]);
76  std::string n = ge->model()->getPhysicalName(ge->dim(), t);
77  if(n.empty()) { sstream << "P" << getDimName(ge->dim()) << t; }
78  else {
79  sstream << n;
80  }
81  }
82  if(withElementary) sstream << " ";
83  }
84  if(withElementary) {
85  sstream << getDimName(ge->dim());
86  // 5 digits with 0 padding
87  if((ge->dim() == 0 && ge->model()->getNumVertices() < 10000) ||
88  (ge->dim() == 1 && ge->model()->getNumEdges() < 10000) ||
89  (ge->dim() == 2 && ge->model()->getNumFaces() < 10000) ||
90  (ge->dim() == 3 && ge->model()->getNumRegions() < 10000))
91  sstream << std::setfill('0') << std::setw(5);
92  sstream << ge->tag();
93  }
94  return sstream.str().substr(0, 32);
95 }
96 
97 static std::string getInterfaceName(GEntity *ge, GEntity *ge1, GEntity *ge2)
98 {
99  std::ostringstream sstream;
100  sstream << getZoneName(ge, false) << " (" << getZoneName(ge1, false) << " & "
101  << getZoneName(ge2, false) << ")";
102  return sstream.str().substr(0, 32);
103 }
104 
105 static void computeTransform2D(const std::vector<cgsize_t> &pointRange,
106  const std::vector<cgsize_t> &pointDonorRange,
107  int type, int typeDonor, int transform[2])
108 {
109  if(pointRange.size() != 4 || pointDonorRange.size() != 4) {
110  Msg::Error("Invalid point ranges to compute transform - using default");
111  transform[0] = 1;
112  transform[1] = 2;
113  return;
114  }
115 
116  int r[2], d[2];
117  for(int i = 0; i < 2; i++) {
118  r[i] = pointRange[i + 2] - pointRange[i];
119  d[i] = pointDonorRange[i + 2] - pointDonorRange[i];
120  }
121  for(int i = 0; i < 2; i++) {
122  transform[i] = 0;
123  for(int j = 0; j < 2; j++) {
124  if(std::abs(r[i]) == std::abs(d[j])) { // == 0 on an interface
125  transform[i] = j + 1;
126  if(!r[i] && !d[j]) { // on an interface
127  // both interfaces correspond to a min index or to a max index
128  if(type == typeDonor) transform[i] *= -1;
129  }
130  else {
131  if(r[i] * d[j] < 0) transform[i] *= -1;
132  }
133  }
134  }
135  if(!transform[i]) Msg::Warning("Could not identify transform[%d]", i);
136  }
137 }
138 
139 static bool findRange2D(GFace *gf, GEdge *ge, int &ibeg, int &jbeg, int &iend,
140  int &jend, int &type)
141 {
142  GVertex *gv1 = ge->getBeginVertex(), *gv2 = ge->getEndVertex();
143  if(!gv1 || !gv1->getNumMeshVertices() || !gv2 || !gv2->getNumMeshVertices())
144  return false;
145  MVertex *v1 = gv1->getMeshVertex(0), *v2 = gv2->getMeshVertex(0);
146  std::vector<std::vector<MVertex *> > &v = gf->transfinite_vertices;
147  int imax = v.size(), jmax = v[0].size();
148  ibeg = iend = jbeg = jend = type = -1;
149  for(int i = 0; i < imax; i++) {
150  for(int j = 0; j < jmax; j++) {
151  if(i == 0 || j == 0 || i == imax - 1 || j == jmax - 1) {
152  if(v[i][j] == v1) {
153  ibeg = i + 1;
154  jbeg = j + 1;
155  }
156  else if(v[i][j] == v2) {
157  iend = i + 1;
158  jend = j + 1;
159  }
160  }
161  }
162  }
163  if(ibeg > 0 && iend > 0 && jbeg > 0 && jend > 0) {
164  if(ibeg == iend && ibeg == 1) type = 1; // imin interface
165  else if(ibeg == iend && ibeg == imax) type = 2; // imax interface
166  else if(jbeg == jend && jbeg == 1) type = 1; // jmin interface
167  else if(jbeg == jend && jbeg == jmax) type = 2; // jmax interface
168  return true;
169  }
170  return false;
171 }
172 
173 static int writeInterface2D(int cgIndexFile, int cgIndexBase, int cgIndexZone,
174  GFace *gf, GEdge *ge, GFace *gf2)
175 {
176  std::vector<cgsize_t> pointRange, pointDonorRange;
177  int ibeg, iend, jbeg, jend, type, typeDonor;
178  if(findRange2D(gf, ge, ibeg, jbeg, iend, jend, type))
179  pointRange = {ibeg, jbeg, iend, jend};
180  if(findRange2D(gf2, ge, ibeg, jbeg, iend, jend, typeDonor))
181  pointDonorRange = {ibeg, jbeg, iend, jend};
182  if(pointRange.size() && pointDonorRange.size()) {
183  int transform[2];
184  computeTransform2D(pointRange, pointDonorRange, type, typeDonor, transform);
185  int cgIndexConn;
186  if(cg_1to1_write(cgIndexFile, cgIndexBase, cgIndexZone,
187  getInterfaceName(ge, gf, gf2).c_str(),
188  getZoneName(gf2).c_str(), &pointRange[0],
189  &pointDonorRange[0], transform, &cgIndexConn) != CG_OK) {
190  return cgnsError(__FILE__, __LINE__, cgIndexFile);
191  }
192  }
193  else {
194  Msg::Warning("Could not identify interface between surfaces %d and %d, "
195  "on curve %d",
196  gf->tag(), gf2->tag(), ge->tag());
197  }
198  return 1;
199 }
200 
201 static int writeBC2D(int cgIndexFile, int cgIndexBase, int cgIndexZone,
202  GFace *gf, GEdge *ge)
203 {
204  int ibeg, iend, jbeg, jend, type;
205  if(findRange2D(gf, ge, ibeg, jbeg, iend, jend, type)) {
206  std::vector<cgsize_t> pointRange = {ibeg, jbeg, iend, jend};
207  // make sure, as in ICEM, that for BCs iend >= ibeg and jend >= jbeg
208  if(iend < ibeg) { pointRange[0] = iend; pointRange[2] = ibeg; }
209  if(jend < jbeg) { pointRange[1] = jend; pointRange[3] = jbeg; }
210  int cgIndexBoco = 0;
211  if(cg_boco_write(cgIndexFile, cgIndexBase, cgIndexZone,
212  getZoneName(ge).c_str(), CGNS_ENUMV(BCTypeNull),
213  CGNS_ENUMV(PointRange), 2, &pointRange[0],
214  &cgIndexBoco) != CG_OK) {
215  return cgnsError(__FILE__, __LINE__, cgIndexFile);
216  }
217  // if the curve is part of a physical group, also write a family
218  if(ge->physicals.size()) {
219  if(cg_goto(cgIndexFile, cgIndexBase, "Zone_t", cgIndexZone, "ZoneBC_t", 1,
220  "BC_t", cgIndexBoco, "end") != CG_OK)
221  return cgnsError(__FILE__, __LINE__, cgIndexFile);
222  if(cg_famname_write(getZoneName(ge, true, false).c_str()) != CG_OK)
223  return cgnsError(__FILE__, __LINE__, cgIndexFile);
224  }
225  }
226  else {
227  Msg::Warning("Could not identify boundary condition on curve %d in "
228  "surface %d",
229  ge->tag(), gf->tag());
230  }
231  return 1;
232 }
233 
234 static int writeZonesStruct2D(int cgIndexFile, int cgIndexBase,
235  std::vector<GFace *> &faces, double scalingFactor)
236 {
237  for(auto gf : faces) {
238  cgsize_t imax = gf->transfinite_vertices.size();
239  cgsize_t jmax = gf->transfinite_vertices[0].size();
240 
241  // write zone
242  int cgIndexZone = 0;
243  cgsize_t cgZoneSize[6] = {imax, jmax, imax - 1, jmax - 1, 0, 0};
244  std::string zoneName = cgnsString(getZoneName(gf));
245  if(cg_zone_write(cgIndexFile, cgIndexBase, zoneName.c_str(), cgZoneSize,
246  CGNS_ENUMV(Structured), &cgIndexZone) != CG_OK)
247  return cgnsError(__FILE__, __LINE__, cgIndexFile);
248 
249  // write grid
250  int cgIndexGrid = 0;
251  if(cg_grid_write(cgIndexFile, cgIndexBase, cgIndexZone, "GridCoordinates",
252  &cgIndexGrid) != CG_OK)
253  return cgnsError(__FILE__, __LINE__, cgIndexFile);
254 
255  // write x coordinates
256  int cgIndexCoord = 0;
257  std::vector<double> data(cgZoneSize[0] * cgZoneSize[1]);
258  for(cgsize_t j = 0; j < jmax; j++) {
259  for(cgsize_t i = 0; i < imax; i++) {
260  MVertex *v = gf->transfinite_vertices[i][j];
261  data[cgZoneSize[0] * j + i] = v->x() * scalingFactor;
262  }
263  }
264  if(cg_coord_write(cgIndexFile, cgIndexBase, cgIndexZone,
265  CGNS_ENUMV(RealDouble), "CoordinateX", &data[0],
266  &cgIndexCoord) != CG_OK)
267  return cgnsError(__FILE__, __LINE__, cgIndexFile);
268 
269  // write y coordinates
270  for(cgsize_t j = 0; j < jmax; j++) {
271  for(cgsize_t i = 0; i < imax; i++) {
272  MVertex *v = gf->transfinite_vertices[i][j];
273  data[cgZoneSize[0] * j + i] = v->y() * scalingFactor;
274  }
275  }
276  if(cg_coord_write(cgIndexFile, cgIndexBase, cgIndexZone,
277  CGNS_ENUMV(RealDouble), "CoordinateY", &data[0],
278  &cgIndexCoord) != CG_OK)
279  return cgnsError(__FILE__, __LINE__, cgIndexFile);
280 
281  // write z coordinates
282  for(cgsize_t j = 0; j < jmax; j++) {
283  for(cgsize_t i = 0; i < imax; i++) {
284  MVertex *v = gf->transfinite_vertices[i][j];
285  data[cgZoneSize[0] * j + i] = v->z() * scalingFactor;
286  }
287  }
288  if(cg_coord_write(cgIndexFile, cgIndexBase, cgIndexZone,
289  CGNS_ENUMV(RealDouble), "CoordinateZ", &data[0],
290  &cgIndexCoord) != CG_OK)
291  return cgnsError(__FILE__, __LINE__, cgIndexFile);
292 
293  for(auto ge : gf->edges()) {
294  // write interface data
295  for(auto gf2 : ge->faces()) {
296  if(gf2 != gf && isTransfinite(gf2))
297  writeInterface2D(cgIndexFile, cgIndexBase, cgIndexZone, gf, ge, gf2);
298  }
299  // write boundary condition for each curve (even those that don't belong
300  // to a physical group, to match ICEM)
301  writeBC2D(cgIndexFile, cgIndexBase, cgIndexZone, gf, ge);
302  }
303  }
304  return 1;
305 }
306 
307 static void computeTransform3D(const std::vector<cgsize_t> &pointRange,
308  const std::vector<cgsize_t> &pointDonorRange,
309  int type, int typeDonor,
310  int transform[3])
311 {
312  if(pointRange.size() != 6 || pointDonorRange.size() != 6) {
313  Msg::Error("Invalid point ranges to compute transform - using default");
314  transform[0] = 1;
315  transform[1] = 2;
316  transform[2] = 3;
317  return;
318  }
319  // This will choose one of the 2 possible orientations if we have the same
320  // number of nodes on all the sides of the interface; not sure if this is an
321  // issue, as the transfinite points ordering is not linked with the geometry
322  // anyway?
323  int r[3], d[3];
324  for(int i = 0; i < 3; i++) {
325  r[i] = pointRange[i + 3] - pointRange[i];
326  d[i] = pointDonorRange[i + 3] - pointDonorRange[i];
327  }
328  for(int i = 0; i < 3; i++) {
329  transform[i] = 0;
330  for(int j = 0; j < 3; j++) {
331  if(std::abs(r[i]) == std::abs(d[j])) { // == 0 on an interface
332  transform[i] = j + 1;
333  if(!r[i] && !d[j]) { // on an interface
334  // both interfaces correspond to a min index or to a max index
335  if(type == typeDonor) transform[i] *= -1;
336  }
337  else {
338  if(r[i] * d[j] < 0) transform[i] *= -1;
339  }
340  }
341  }
342  if(!transform[i]) Msg::Warning("Could not identify transform[%d]", i);
343  }
344 }
345 
346 static bool findRange3D(GRegion *gr, GFace *gf, int &ibeg, int &jbeg, int &kbeg,
347  int &iend, int &jend, int &kend, int &type)
348 {
349  if(gf->transfinite_vertices.empty() || gf->transfinite_vertices[0].empty())
350  return false;
351  MVertex *v1 = gf->transfinite_vertices.front().front();
352  MVertex *v2 = gf->transfinite_vertices.back().back();
353 
354  std::vector<std::vector<std::vector<MVertex *> > > &v =
356  int imax = v.size(), jmax = v[0].size(), kmax = v[0][0].size();
357  ibeg = iend = jbeg = jend = kbeg = kend = type = -1;
358  for(int i = 0; i < imax; i++) {
359  for(int j = 0; j < jmax; j++) {
360  for(int k = 0; k < kmax; k++) {
361  if(i == 0 || j == 0 || k == 0 || i == imax - 1 || j == jmax - 1 ||
362  k == kmax - 1) {
363  if(v[i][j][k] == v1) {
364  ibeg = i + 1;
365  jbeg = j + 1;
366  kbeg = k + 1;
367  }
368  else if(v[i][j][k] == v2) {
369  iend = i + 1;
370  jend = j + 1;
371  kend = k + 1;
372  }
373  }
374  }
375  }
376  }
377  if(ibeg > 0 && iend > 0 && jbeg > 0 && jend > 0 && kbeg > 0 && kend > 0) {
378  if(ibeg == iend && ibeg == 1) type = 1; // imin interface
379  else if(ibeg == iend && ibeg == imax) type = 2; // imax interface
380  else if(jbeg == jend && jbeg == 1) type = 1; // jmin interface
381  else if(jbeg == jend && jbeg == jmax) type = 2; // jmax interface
382  else if(kbeg == kend && kbeg == 1) type = 1; // kmin interface
383  else if(kbeg == kend && kbeg == kmax) type = 2; // kmax interface
384  return true;
385  }
386  return false;
387 }
388 
389 static int writeInterface3D(int cgIndexFile, int cgIndexBase, int cgIndexZone,
390  GRegion *gr, GFace *gf, GRegion *gr2)
391 {
392  std::vector<cgsize_t> pointRange, pointDonorRange;
393  int ibeg, iend, jbeg, jend, kbeg, kend, type, typeDonor;
394  if(findRange3D(gr, gf, ibeg, jbeg, kbeg, iend, jend, kend, type))
395  pointRange = {ibeg, jbeg, kbeg, iend, jend, kend};
396  if(findRange3D(gr2, gf, ibeg, jbeg, kbeg, iend, jend, kend, typeDonor))
397  pointDonorRange = {ibeg, jbeg, kbeg, iend, jend, kend};
398  if(pointRange.size() && pointDonorRange.size()) {
399  int transform[3];
400  computeTransform3D(pointRange, pointDonorRange, type, typeDonor, transform);
401  int cgIndexConn;
402  if(cg_1to1_write(cgIndexFile, cgIndexBase, cgIndexZone,
403  getInterfaceName(gf, gr, gr2).c_str(),
404  getZoneName(gr2).c_str(), &pointRange[0],
405  &pointDonorRange[0], transform, &cgIndexConn) != CG_OK) {
406  return cgnsError(__FILE__, __LINE__, cgIndexFile);
407  }
408  }
409  else {
410  Msg::Warning("Could not identify interface between volumes %d and %d, "
411  "on surface %d",
412  gr->tag(), gr2->tag(), gf->tag());
413  }
414  return 1;
415 }
416 
417 static int writeBC3D(int cgIndexFile, int cgIndexBase, int cgIndexZone,
418  GRegion *gr, GFace *gf)
419 {
420  int ibeg, iend, jbeg, jend, kbeg, kend, type;
421  if(findRange3D(gr, gf, ibeg, jbeg, kbeg, iend, jend, kend, type)) {
422  std::vector<cgsize_t> pointRange = {ibeg, jbeg, kbeg, iend, jend, kend};
423  // make sure, as in ICEM, that for BCs iend >= ibeg, jend >= jbeg and kend
424  // >= kbeg
425  if(iend < ibeg) { pointRange[0] = iend; pointRange[3] = ibeg; }
426  if(jend < jbeg) { pointRange[1] = jend; pointRange[4] = jbeg; }
427  if(kend < kbeg) { pointRange[2] = kend; pointRange[5] = kbeg; }
428  int cgIndexBoco = 0;
429  if(cg_boco_write(cgIndexFile, cgIndexBase, cgIndexZone,
430  getZoneName(gf).c_str(), CGNS_ENUMV(BCTypeNull),
431  CGNS_ENUMV(PointRange), 2, &pointRange[0],
432  &cgIndexBoco) != CG_OK) {
433  return cgnsError(__FILE__, __LINE__, cgIndexFile);
434  }
435  // if the surface is part of a physical group, also write a family
436  if(gf->physicals.size()) {
437  if(cg_goto(cgIndexFile, cgIndexBase, "Zone_t", cgIndexZone, "ZoneBC_t", 1,
438  "BC_t", cgIndexBoco, "end") != CG_OK)
439  return cgnsError(__FILE__, __LINE__, cgIndexFile);
440  if(cg_famname_write(getZoneName(gf, true, false).c_str()) != CG_OK)
441  return cgnsError(__FILE__, __LINE__, cgIndexFile);
442  }
443  }
444  else {
445  Msg::Warning("Could not identify boundary condition on surface %d in "
446  "volume %d",
447  gf->tag(), gr->tag());
448  }
449  return 1;
450 }
451 
452 static int writeZonesStruct3D(int cgIndexFile, int cgIndexBase,
453  std::vector<GRegion *> &regions,
454  double scalingFactor)
455 {
456  for(auto gr : regions) {
457  cgsize_t imax = gr->transfinite_vertices.size();
458  cgsize_t jmax = gr->transfinite_vertices[0].size();
459  cgsize_t kmax = gr->transfinite_vertices[0][0].size();
460 
461  // write zone
462  int cgIndexZone = 0;
463  cgsize_t cgZoneSize[9] = {imax, jmax, kmax, imax - 1, jmax - 1,
464  kmax - 1, 0, 0, 0};
465  std::string zoneName = cgnsString(getZoneName(gr));
466  if(cg_zone_write(cgIndexFile, cgIndexBase, zoneName.c_str(), cgZoneSize,
467  CGNS_ENUMV(Structured), &cgIndexZone) != CG_OK)
468  return cgnsError(__FILE__, __LINE__, cgIndexFile);
469 
470  // write grid
471  int cgIndexGrid = 0;
472  if(cg_grid_write(cgIndexFile, cgIndexBase, cgIndexZone, "GridCoordinates",
473  &cgIndexGrid) != CG_OK)
474  return cgnsError(__FILE__, __LINE__, cgIndexFile);
475 
476  // write x coordinates
477  int cgIndexCoord = 0;
478  std::vector<double> data(imax * jmax * kmax);
479  for(cgsize_t k = 0; k < kmax; k++) {
480  for(cgsize_t j = 0; j < jmax; j++) {
481  for(cgsize_t i = 0; i < imax; i++) {
482  MVertex *v = gr->transfinite_vertices[i][j][k];
483  data[imax * jmax * k + imax * j + i] = v->x() * scalingFactor;
484  }
485  }
486  }
487  if(cg_coord_write(cgIndexFile, cgIndexBase, cgIndexZone,
488  CGNS_ENUMV(RealDouble), "CoordinateX", &data[0],
489  &cgIndexCoord) != CG_OK)
490  return cgnsError(__FILE__, __LINE__, cgIndexFile);
491 
492  // write y coordinates
493  for(cgsize_t k = 0; k < kmax; k++) {
494  for(cgsize_t j = 0; j < jmax; j++) {
495  for(cgsize_t i = 0; i < imax; i++) {
496  MVertex *v = gr->transfinite_vertices[i][j][k];
497  data[imax * jmax * k + imax * j + i] = v->y() * scalingFactor;
498  }
499  }
500  }
501  if(cg_coord_write(cgIndexFile, cgIndexBase, cgIndexZone,
502  CGNS_ENUMV(RealDouble), "CoordinateY", &data[0],
503  &cgIndexCoord) != CG_OK)
504  return cgnsError(__FILE__, __LINE__, cgIndexFile);
505 
506  // write z coordinates
507  for(cgsize_t k = 0; k < kmax; k++) {
508  for(cgsize_t j = 0; j < jmax; j++) {
509  for(cgsize_t i = 0; i < imax; i++) {
510  MVertex *v = gr->transfinite_vertices[i][j][k];
511  data[imax * jmax * k + imax * j + i] = v->z() * scalingFactor;
512  }
513  }
514  }
515  if(cg_coord_write(cgIndexFile, cgIndexBase, cgIndexZone,
516  CGNS_ENUMV(RealDouble), "CoordinateZ", &data[0],
517  &cgIndexCoord) != CG_OK)
518  return cgnsError(__FILE__, __LINE__, cgIndexFile);
519 
520  for(auto gf : gr->faces()) {
521  // write interface data
522  for(auto gr2 : gf->regions()) {
523  if(gr2 != gr && isTransfinite(gr2))
524  writeInterface3D(cgIndexFile, cgIndexBase, cgIndexZone, gr, gf, gr2);
525  }
526  // write boundary condition for each surface (even those that don't belong
527  // to a physical group, to match ICEM)
528  writeBC3D(cgIndexFile, cgIndexBase, cgIndexZone, gr, gf);
529  }
530  }
531  return 1;
532 }
533 
534 int writeZonesStruct(GModel *model, double scalingFactor, int cgIndexFile,
535  int cgIndexBase)
536 {
537  int meshDim = -1;
538 
539  std::vector<GFace *> faces;
540  for(auto it = model->firstFace(); it != model->lastFace(); ++it) {
541  if(isTransfinite(*it)) {
542  meshDim = 2;
543  faces.push_back(*it);
544  }
545  }
546 
547  std::vector<GRegion *> regions;
548  for(auto it = model->firstRegion(); it != model->lastRegion(); ++it) {
549  if(isTransfinite(*it)) {
550  meshDim = 3;
551  regions.push_back(*it);
552  }
553  }
554 
555  if(meshDim < 0 || (faces.empty() && regions.empty())) {
556  Msg::Warning("No structured meshes to save");
557  return 0;
558  }
559 
560  if(meshDim == 2) {
561  if(writeZonesStruct2D(cgIndexFile, cgIndexBase, faces, scalingFactor))
562  return 1;
563  }
564  else if(meshDim == 3) {
565  if(writeZonesStruct3D(cgIndexFile, cgIndexBase, regions, scalingFactor))
566  return 1;
567  }
568 
569  return 0;
570 }
571 
572 #endif // HAVE_LIBCGNS
GFace::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GFace.h:121
GEntity::getMeshVertex
MVertex * getMeshVertex(std::size_t index)
Definition: GEntity.h:379
GFace
Definition: GFace.h:33
GEntity::model
GModel * model() const
Definition: GEntity.h:277
MVertex
Definition: MVertex.h:24
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
MVertex::z
double z() const
Definition: MVertex.h:62
GEntity::physicals
std::vector< int > physicals
Definition: GEntity.h:65
transform
static SPoint3 transform(MVertex *vsource, const std::vector< double > &tfo)
Definition: Generator.cpp:1347
GRegion::transfinite_vertices
std::vector< std::vector< std::vector< MVertex * > > > transfinite_vertices
Definition: GRegion.h:161
GEntity
Definition: GEntity.h:31
GEntity::getNumMeshVertices
std::size_t getNumMeshVertices()
Definition: GEntity.h:376
GFace::regions
std::list< GRegion * > regions() const
Definition: GFace.h:92
GRegion::faces
virtual std::vector< GFace * > faces() const
Definition: GRegion.h:64
GModel::lastFace
fiter lastFace()
Definition: GModel.h:359
GModel::getPhysicalName
std::string getPhysicalName(int dim, int num) const
Definition: GModel.cpp:961
GVertex
Definition: GVertex.h:23
GModel::getNumVertices
std::size_t getNumVertices() const
Definition: GModel.h:347
GModel
Definition: GModel.h:44
GEdge::getBeginVertex
virtual GVertex * getBeginVertex() const
Definition: GEdge.h:63
GModel::firstFace
fiter firstFace()
Definition: GModel.h:355
GModel::getNumRegions
std::size_t getNumRegions() const
Definition: GModel.h:344
GEntity::tag
int tag() const
Definition: GEntity.h:280
GModel::getNumFaces
std::size_t getNumFaces() const
Definition: GModel.h:345
CGNSConventions.h
GRegion
Definition: GRegion.h:28
CGNSCommon.h
GModel::getNumEdges
std::size_t getNumEdges() const
Definition: GModel.h:346
GEdge::faces
virtual std::vector< GFace * > faces() const
Definition: GEdge.h:113
GModel::firstRegion
riter firstRegion()
Definition: GModel.h:354
GModel::lastRegion
riter lastRegion()
Definition: GModel.h:358
Context.h
GEdge
Definition: GEdge.h:26
GFace::transfinite_vertices
std::vector< std::vector< MVertex * > > transfinite_vertices
Definition: GFace.h:420
GModel.h
MVertex::y
double y() const
Definition: MVertex.h:61
GEdge::getEndVertex
virtual GVertex * getEndVertex() const
Definition: GEdge.h:64
GEntity::dim
virtual int dim() const
Definition: GEntity.h:196
MVertex::x
double x() const
Definition: MVertex.h:60
faces
static int faces[4][3]
Definition: meshGRegionDelaunayInsertion.cpp:165