42 #if defined(HAVE_LIBCGNS)
44 static bool isTransfinite(
GFace *gf)
49 static bool isTransfinite(
GRegion *gr)
56 static std::string getDimName(
int 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;
67 static std::string getZoneName(
GEntity *ge,
bool withPhysical =
true,
68 bool withElementary =
true)
70 std::ostringstream sstream;
73 for(std::size_t i = 0; i < ge->
physicals.size(); i++) {
77 if(n.empty()) { sstream <<
"P" << getDimName(ge->
dim()) << t; }
82 if(withElementary) sstream <<
" ";
85 sstream << getDimName(ge->
dim());
91 sstream << std::setfill(
'0') << std::setw(5);
94 return sstream.str().substr(0, 32);
99 std::ostringstream sstream;
100 sstream << getZoneName(ge,
false) <<
" (" << getZoneName(ge1,
false) <<
" & "
101 << getZoneName(ge2,
false) <<
")";
102 return sstream.str().substr(0, 32);
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])
109 if(pointRange.size() != 4 || pointDonorRange.size() != 4) {
110 Msg::Error(
"Invalid point ranges to compute transform - using default");
117 for(
int i = 0; i < 2; i++) {
118 r[i] = pointRange[i + 2] - pointRange[i];
119 d[i] = pointDonorRange[i + 2] - pointDonorRange[i];
121 for(
int i = 0; i < 2; i++) {
123 for(
int j = 0; j < 2; j++) {
124 if(std::abs(r[i]) == std::abs(d[j])) {
128 if(type == typeDonor)
transform[i] *= -1;
139 static bool findRange2D(
GFace *gf,
GEdge *ge,
int &ibeg,
int &jbeg,
int &iend,
140 int &jend,
int &type)
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) {
156 else if(v[i][j] == v2) {
163 if(ibeg > 0 && iend > 0 && jbeg > 0 && jend > 0) {
164 if(ibeg == iend && ibeg == 1) type = 1;
165 else if(ibeg == iend && ibeg == imax) type = 2;
166 else if(jbeg == jend && jbeg == 1) type = 1;
167 else if(jbeg == jend && jbeg == jmax) type = 2;
173 static int writeInterface2D(
int cgIndexFile,
int cgIndexBase,
int cgIndexZone,
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()) {
184 computeTransform2D(pointRange, pointDonorRange, type, typeDonor,
transform);
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);
194 Msg::Warning(
"Could not identify interface between surfaces %d and %d, "
201 static int writeBC2D(
int cgIndexFile,
int cgIndexBase,
int cgIndexZone,
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};
208 if(iend < ibeg) { pointRange[0] = iend; pointRange[2] = ibeg; }
209 if(jend < jbeg) { pointRange[1] = jend; pointRange[3] = jbeg; }
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);
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);
227 Msg::Warning(
"Could not identify boundary condition on curve %d in "
234 static int writeZonesStruct2D(
int cgIndexFile,
int cgIndexBase,
235 std::vector<GFace *> &
faces,
double scalingFactor)
237 for(
auto gf :
faces) {
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);
251 if(cg_grid_write(cgIndexFile, cgIndexBase, cgIndexZone,
"GridCoordinates",
252 &cgIndexGrid) != CG_OK)
253 return cgnsError(__FILE__, __LINE__, cgIndexFile);
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++) {
261 data[cgZoneSize[0] * j + i] = v->
x() * scalingFactor;
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);
270 for(cgsize_t j = 0; j < jmax; j++) {
271 for(cgsize_t i = 0; i < imax; i++) {
273 data[cgZoneSize[0] * j + i] = v->
y() * scalingFactor;
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);
282 for(cgsize_t j = 0; j < jmax; j++) {
283 for(cgsize_t i = 0; i < imax; i++) {
285 data[cgZoneSize[0] * j + i] = v->
z() * scalingFactor;
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);
293 for(
auto ge : gf->
edges()) {
295 for(
auto gf2 : ge->
faces()) {
296 if(gf2 != gf && isTransfinite(gf2))
297 writeInterface2D(cgIndexFile, cgIndexBase, cgIndexZone, gf, ge, gf2);
301 writeBC2D(cgIndexFile, cgIndexBase, cgIndexZone, gf, ge);
307 static void computeTransform3D(
const std::vector<cgsize_t> &pointRange,
308 const std::vector<cgsize_t> &pointDonorRange,
309 int type,
int typeDonor,
312 if(pointRange.size() != 6 || pointDonorRange.size() != 6) {
313 Msg::Error(
"Invalid point ranges to compute transform - using default");
324 for(
int i = 0; i < 3; i++) {
325 r[i] = pointRange[i + 3] - pointRange[i];
326 d[i] = pointDonorRange[i + 3] - pointDonorRange[i];
328 for(
int i = 0; i < 3; i++) {
330 for(
int j = 0; j < 3; j++) {
331 if(std::abs(r[i]) == std::abs(d[j])) {
335 if(type == typeDonor)
transform[i] *= -1;
346 static bool findRange3D(
GRegion *gr,
GFace *gf,
int &ibeg,
int &jbeg,
int &kbeg,
347 int &iend,
int &jend,
int &kend,
int &type)
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 ||
363 if(v[i][j][k] == v1) {
368 else if(v[i][j][k] == v2) {
377 if(ibeg > 0 && iend > 0 && jbeg > 0 && jend > 0 && kbeg > 0 && kend > 0) {
378 if(ibeg == iend && ibeg == 1) type = 1;
379 else if(ibeg == iend && ibeg == imax) type = 2;
380 else if(jbeg == jend && jbeg == 1) type = 1;
381 else if(jbeg == jend && jbeg == jmax) type = 2;
382 else if(kbeg == kend && kbeg == 1) type = 1;
383 else if(kbeg == kend && kbeg == kmax) type = 2;
389 static int writeInterface3D(
int cgIndexFile,
int cgIndexBase,
int cgIndexZone,
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()) {
400 computeTransform3D(pointRange, pointDonorRange, type, typeDonor,
transform);
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);
410 Msg::Warning(
"Could not identify interface between volumes %d and %d, "
417 static int writeBC3D(
int cgIndexFile,
int cgIndexBase,
int cgIndexZone,
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};
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; }
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);
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);
445 Msg::Warning(
"Could not identify boundary condition on surface %d in "
452 static int writeZonesStruct3D(
int cgIndexFile,
int cgIndexBase,
453 std::vector<GRegion *> ®ions,
454 double scalingFactor)
456 for(
auto gr : regions) {
463 cgsize_t cgZoneSize[9] = {imax, jmax, kmax, imax - 1, jmax - 1,
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);
472 if(cg_grid_write(cgIndexFile, cgIndexBase, cgIndexZone,
"GridCoordinates",
473 &cgIndexGrid) != CG_OK)
474 return cgnsError(__FILE__, __LINE__, cgIndexFile);
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++) {
483 data[imax * jmax * k + imax * j + i] = v->
x() * scalingFactor;
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);
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++) {
497 data[imax * jmax * k + imax * j + i] = v->
y() * scalingFactor;
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);
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++) {
511 data[imax * jmax * k + imax * j + i] = v->
z() * scalingFactor;
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);
520 for(
auto gf : gr->
faces()) {
522 for(
auto gr2 : gf->
regions()) {
523 if(gr2 != gr && isTransfinite(gr2))
524 writeInterface3D(cgIndexFile, cgIndexBase, cgIndexZone, gr, gf, gr2);
528 writeBC3D(cgIndexFile, cgIndexBase, cgIndexZone, gr, gf);
534 int writeZonesStruct(
GModel *model,
double scalingFactor,
int cgIndexFile,
539 std::vector<GFace *>
faces;
541 if(isTransfinite(*it)) {
543 faces.push_back(*it);
547 std::vector<GRegion *> regions;
549 if(isTransfinite(*it)) {
551 regions.push_back(*it);
555 if(meshDim < 0 || (
faces.empty() && regions.empty())) {
561 if(writeZonesStruct2D(cgIndexFile, cgIndexBase,
faces, scalingFactor))
564 else if(meshDim == 3) {
565 if(writeZonesStruct3D(cgIndexFile, cgIndexBase, regions, scalingFactor))
572 #endif // HAVE_LIBCGNS