18 #if defined(HAVE_LIBCGNS)
23 MElement *createElement(
const cgsize_t *ijk,
const cgsize_t *nijk,
int order,
24 std::size_t vertShift,
25 std::vector<MVertex *> &allVert,
26 std::map<
int, std::vector<MElement *> > *allElt);
28 void initLinShift(
int order,
int *shift)
31 for(
int i = 0; i < mono.
size1(); i++) {
32 shift[i] = mono(i, 0) + 0.5;
36 void initQuadShift(
int order,
int *shift)
39 for(
int i = 0; i < mono.
size1(); i++) {
40 for(
int j = 0; j < 2; j++)
41 shift[i * 2 + j] = mono(i, j) + 0.5;
45 void initHexShift(
int order,
int *shift)
48 for(
int i = 0; i < mono.
size1(); i++) {
49 for(
int j = 0; j < 3; j++)
50 shift[i * 3 + j] = mono(i, j) + 0.5;
55 MElement *createElement<2>(
const cgsize_t *ijk,
const cgsize_t *nijk,
56 int order, std::size_t vertShift,
57 std::vector<MVertex *> &allVert,
58 std::map<
int, std::vector<MElement *> > *allElt)
61 static int shiftP1[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
62 static int shiftP2[9][2] = {{0, 0}, {2, 0}, {2, 2}, {0, 2}, {1, 0},
63 {2, 1}, {1, 2}, {0, 1}, {1, 1}};
77 std::vector<MVertex *> eltVert(nbEltNode);
78 for(
int iN = 0; iN < nbEltNode; iN++) {
79 const cgsize_t ijN[3] = {ijk[0] + s[2 * iN], ijk[1] + s[2 * iN + 1]};
80 const int ind = vertShift + ijk2Ind<2>(ijN, nijk);
81 eltVert[iN] = allVert[ind];
90 allElt[3][entity].push_back(e);
96 MElement *createElement<3>(
const cgsize_t *ijk,
const cgsize_t *nijk,
97 int order, std::size_t vertShift,
98 std::vector<MVertex *> &allVert,
99 std::map<
int, std::vector<MElement *> > *allElt)
102 static bool isShiftInit[4] = {
false,
false,
false,
false};
103 static int shiftP1[8 * 3], shiftP2[27 * 3], shiftP3[64 * 3],
112 if(!isShiftInit[0]) {
113 initHexShift(1, shiftP1);
114 isShiftInit[0] =
true;
120 if(!isShiftInit[1]) {
121 initHexShift(2, shiftP2);
122 isShiftInit[1] =
true;
128 if(!isShiftInit[2]) {
129 initHexShift(3, shiftP3);
130 isShiftInit[2] =
true;
136 if(!isShiftInit[3]) {
137 initHexShift(4, shiftP4);
138 isShiftInit[3] =
true;
143 Msg::Error(
"Cannot coarsen structured zone to order %i, falling back to "
147 if(!isShiftInit[0]) {
148 initHexShift(1, shiftP1);
149 isShiftInit[0] =
true;
155 std::vector<MVertex *> eltVert(nbEltNode);
156 for(
int iN = 0; iN < nbEltNode; iN++) {
157 const cgsize_t ijkN[3] = {ijk[0] + s[3 * iN], ijk[1] + s[3 * iN + 1],
158 ijk[2] + s[3 * iN + 2]};
159 const cgsize_t ind = vertShift + ijk2Ind<3>(ijkN, nijk);
160 eltVert[iN] = allVert[ind];
169 allElt[5][entity].push_back(e);
175 MElement *createBndElement(
const cgsize_t *ijk,
const cgsize_t *nijk,
176 const int *dir,
int order,
int entity,
177 std::size_t vertShift,
178 std::vector<MVertex *> &allVert,
179 std::map<
int, std::vector<MElement *> > *allElt,
180 const std::vector<bool> &interfaceNode);
183 MElement *createBndElement<2>(
const cgsize_t *ijk,
const cgsize_t *nijk,
184 const int *dir,
int order,
int entity,
185 std::size_t vertShift,
186 std::vector<MVertex *> &allVert,
187 std::map<
int, std::vector<MElement *> > *allElt,
188 const std::vector<bool> &interfaceNode)
191 static bool isShiftInit[4] = {
false,
false,
false,
false};
192 static int shiftP1[2], shiftP2[3], shiftP3[4], shiftP4[5];
200 if(!isShiftInit[0]) {
201 initLinShift(1, shiftP1);
202 isShiftInit[0] =
true;
208 if(!isShiftInit[1]) {
209 initLinShift(2, shiftP2);
210 isShiftInit[1] =
true;
216 if(!isShiftInit[2]) {
217 initLinShift(3, shiftP3);
218 isShiftInit[2] =
true;
224 if(!isShiftInit[3]) {
225 initLinShift(4, shiftP4);
226 isShiftInit[3] =
true;
231 Msg::Error(
"Cannot coarsen structured zone to order %i, falling back to "
235 if(!isShiftInit[0]) {
236 initLinShift(1, shiftP1);
237 isShiftInit[0] =
true;
243 std::vector<MVertex *> eltVert(nbEltNode);
244 bool isInternalInterface =
true;
245 for(
int iN = 0; iN < nbEltNode; iN++) {
246 cgsize_t ijN[2] = {ijk[0], ijk[1]};
247 ijN[dir[0]] += s[iN];
248 const cgsize_t ind = ijk2Ind<2>(ijN, nijk);
249 isInternalInterface &= interfaceNode[ind];
250 eltVert[iN] = allVert[vertShift + ind];
254 if(isInternalInterface)
return nullptr;
261 allElt[1][entity].push_back(e);
267 MElement *createBndElement<3>(
const cgsize_t *ijk,
const cgsize_t *nijk,
268 const int *dir,
int order,
int entity,
269 std::size_t vertShift,
270 std::vector<MVertex *> &allVert,
271 std::map<
int, std::vector<MElement *> > *allElt,
272 const std::vector<bool> &interfaceNode)
275 static bool isShiftInit[4] = {
false,
false,
false,
false};
276 static int shiftP1[4 * 2], shiftP2[9 * 2], shiftP3[16 * 2], shiftP4[25 * 2];
284 if(!isShiftInit[0]) {
285 initQuadShift(1, shiftP1);
286 isShiftInit[0] =
true;
292 if(!isShiftInit[1]) {
293 initQuadShift(2, shiftP2);
294 isShiftInit[1] =
true;
300 if(!isShiftInit[2]) {
301 initQuadShift(3, shiftP3);
302 isShiftInit[2] =
true;
308 if(!isShiftInit[3]) {
309 initQuadShift(4, shiftP4);
310 isShiftInit[3] =
true;
315 Msg::Error(
"Cannot coarsen structured zone to order %i, falling back to "
319 if(!isShiftInit[0]) {
320 initQuadShift(1, shiftP1);
321 isShiftInit[0] =
true;
327 std::vector<MVertex *> eltVert(nbEltNode);
328 bool isInternalInterface =
true;
329 for(
int iN = 0; iN < nbEltNode; iN++) {
330 cgsize_t ijkN[3] = {ijk[0], ijk[1], ijk[2]};
331 ijkN[dir[0]] += s[2 * iN];
332 ijkN[dir[1]] += s[2 * iN + 1];
333 const cgsize_t ind = ijk2Ind<3>(ijkN, nijk);
334 isInternalInterface &= interfaceNode[ind];
335 eltVert[iN] = allVert[vertShift + ind];
339 if(isInternalInterface)
return nullptr;
346 allElt[3][entity].push_back(e);
354 CGNSZoneStruct<DIM>::CGNSZoneStruct(
355 int fileIndex,
int baseIndex,
int zoneIndex,
int meshDim, cgsize_t startNode,
356 const Family2EltNodeTransfo &allEltNodeTransfo,
int &err)
357 : CGNSZone(fileIndex, baseIndex, zoneIndex, CGNS_ENUMV(Structured), meshDim,
358 startNode, allEltNodeTransfo, err)
362 for(
int d = 0; d < DIM; d++) ok &= (nbNodeIJK(d) == nbEltIJK(d) + 1);
366 Msg::Error(
"CGNS zone %i: number of vertices (%i, %i, %i) is inconsistent "
367 "with number of elements (%i, %i, %i)",
368 zoneIndex, nbNodeIJK(0), nbNodeIJK(1),
369 (DIM == 3) ? nbNodeIJK(2) : 0, nbEltIJK(0), nbEltIJK(1),
370 (DIM == 3) ? nbEltIJK(2) : 0);
375 nbNode_ = nbTotFromIJK<DIM>(nbNodeIJK());
376 nbElt_ = nbTotFromIJK<DIM>(nbEltIJK());
378 interfaceNode_.resize(nbNode());
382 int CGNSZoneStruct<DIM>::readElements(
383 std::vector<MVertex *> &allVert,
384 std::map<
int, std::vector<MElement *> > *allElt,
385 std::vector<MElement *> &zoneElt, std::vector<std::string> &allGeomName)
388 const int firstDefaultEnt = allGeomName.size();
389 allGeomName.insert(allGeomName.end(), 2 * meshDim(),
"");
394 Msg::Warning(
"Cannot coarsen structured grid to order %i, creating linear "
401 for(
int d = 0; d < DIM; d++) orderOK &= (nbEltIJK(d) % order == 0);
403 Msg::Warning(
"Zone %i has (%i, %i, %i) vertices which cannot be coarsened"
404 " to order %i, creating linear mesh",
405 index(), nbNodeIJK(0), nbNodeIJK(1),
406 (DIM == 3) ? nbNodeIJK(2) : 0, order);
410 const int nbEltI = nbEltIJK(0) / order;
411 const int nbEltJ = nbEltIJK(1) / order;
412 const int nbEltK = (DIM == 3) ? nbEltIJK(2) / order : 1;
415 for(
int k = 0; k < nbEltK; k++) {
416 for(
int j = 0; j < nbEltJ; j++) {
417 for(
int i = 0; i < nbEltI; i++) {
418 const cgsize_t ijk[3] = {i * order, j * order, k * order};
419 MElement *me = createElement<DIM>(ijk, nbNodeIJK(), order, startNode(),
421 zoneElt.push_back(me);
427 for(
int k = 0; k < nbEltK; k++) {
428 for(
int j = 0; j < nbEltJ; j++) {
429 static const int dir[2] = {1, 2};
430 cgsize_t ijk[3] = {0, j * order, k * order};
432 me = makeBndElement(ijk, dir, order, firstDefaultEnt, allVert, allElt);
433 if(me !=
nullptr) zoneElt.push_back(me);
434 ijk[0] = nbNodeIJK(0) - 1;
436 makeBndElement(ijk, dir, order, firstDefaultEnt + 1, allVert, allElt);
437 if(me !=
nullptr) zoneElt.push_back(me);
442 for(
int k = 0; k < nbEltK; k++) {
443 for(
int i = 0; i < nbEltI; i++) {
444 static const int dir[2] = {0, 2};
445 cgsize_t ijk[3] = {i * order, 0, k * order};
448 makeBndElement(ijk, dir, order, firstDefaultEnt + 2, allVert, allElt);
449 if(me !=
nullptr) zoneElt.push_back(me);
450 ijk[1] = nbNodeIJK(1) - 1;
452 makeBndElement(ijk, dir, order, firstDefaultEnt + 3, allVert, allElt);
453 if(me !=
nullptr) zoneElt.push_back(me);
459 for(
int j = 0; j < nbEltJ; j++) {
460 for(
int i = 0; i < nbEltI; i++) {
461 static const int dir[2] = {0, 1};
462 cgsize_t ijk[3] = {i * order, j * order, 0};
465 makeBndElement(ijk, dir, order, firstDefaultEnt + 4, allVert, allElt);
466 if(me !=
nullptr) zoneElt.push_back(me);
467 ijk[2] = nbNodeIJK(2) - 1;
469 makeBndElement(ijk, dir, order, firstDefaultEnt + 5, allVert, allElt);
470 if(me !=
nullptr) zoneElt.push_back(me);
479 MElement *CGNSZoneStruct<DIM>::makeBndElement(
480 const cgsize_t *ijk,
const int *dir,
int order,
int defaultEntity,
481 std::vector<MVertex *> &allVert,
482 std::map<
int, std::vector<MElement *> > *allElt)
484 cgsize_t iElt = ijk2Ind<DIM>(ijk, nbNodeIJK());
485 const auto it = elt2Geom().find(iElt);
486 const int entity = (it == elt2Geom().end()) ? defaultEntity : it->second;
488 return createBndElement<DIM>(ijk, nbNodeIJK(), dir, order, entity,
489 startNode(), allVert, allElt, interfaceNode());
493 int CGNSZoneStruct<DIM>::readConnectivities(
494 const std::map<std::string, int> &name2Zone,
495 std::vector<CGNSZone *> &allZones)
500 CGNSZone::readConnectivities(name2Zone, allZones);
504 cgnsErr = cg_n1to1(fileIndex(), baseIndex(), index(), &nbConnect);
505 if(cgnsErr != CG_OK)
return cgnsError(__FILE__, __LINE__, fileIndex());
508 for(
int iConnect = 1; iConnect <= nbConnect; iConnect++) {
510 err = readOneInterface(iConnect, name2Zone, allZones);
511 if(err == 0)
return 0;
518 int CGNSZoneStruct<DIM>::readOneInterface(
519 int iConnect,
const std::map<std::string, int> &name2Zone,
520 std::vector<CGNSZone *> &allZones)
525 char connectName[CGNS_MAX_STR_LEN], donorName[CGNS_MAX_STR_LEN];
526 cgsize_t range[2 * DIM], rangeDonnor[2 * DIM];
527 int indexTransfo[DIM];
529 cg_1to1_read(fileIndex(), baseIndex(), index(), iConnect, connectName,
530 donorName, range, rangeDonnor, indexTransfo);
531 if(cgnsErr != CG_OK)
return cgnsError(__FILE__, __LINE__, fileIndex());
534 bool periodic =
false;
535 float rotCenter[3], rotAngle[3], translat[3];
536 cgnsErr = cg_1to1_periodic_read(fileIndex(), baseIndex(), index(), iConnect,
537 rotCenter, rotAngle, translat);
538 if(cgnsErr != CG_NODE_NOT_FOUND) {
542 return cgnsError(__FILE__, __LINE__, fileIndex());
547 std::vector<cgsize_t> indNode;
548 nodeFromRange(range, indNode);
549 for(std::size_t i = 0; i < indNode.size(); i++) {
550 interfaceNode_[indNode[i]] =
true;
632 template class CGNSZoneStruct<2>;
633 template class CGNSZoneStruct<3>;
635 #endif // HAVE_LIBCGNS