1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
28 Converts a CFX 4 mesh to OpenFOAM format
30 \*---------------------------------------------------------------------------*/
37 #include "wallPolyPatch.H"
38 #include "symmetryPolyPatch.H"
39 #include "preservePatchTypes.H"
40 #include "cellShape.H"
41 #include "cellModeller.H"
45 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
48 int main(int argc, char *argv[])
50 argList::noParallel();
51 argList::validArgs.append("CFX geom file");
56 "geometry scaling factor - default is 1"
59 argList args(argc, argv);
66 const scalar scaleFactor = args.optionLookupOrDefault("scale", 1.0);
68 # include "createTime.H"
70 IFstream cfxFile(args[1]);
72 // Read the cfx information using a fixed format reader.
73 // Comments in the file are in C++ style, so the stream parser will remove
74 // them with no intervention
75 label nblock, npatch, nglue, nelem, npoint;
77 cfxFile >> nblock >> npatch >> nglue >> nelem >> npoint;
79 Info<< "Reading blocks" << endl;
81 PtrList<hexBlock> blocks(nblock);
87 forAll(blocks, blockI)
90 cfxFile >> nx >> ny >> nz;
92 blocks.set(blockI, new hexBlock(nx, ny, nz));
96 Info<< "Reading patch definitions" << endl;
98 wordList cfxPatchTypes(npatch);
99 wordList cfxPatchNames(npatch);
100 labelList patchMasterBlocks(npatch);
101 labelList patchDirections(npatch);
102 labelListList patchRanges(npatch);
105 label no, blkNo, patchLabel;
107 forAll(cfxPatchTypes, patchI)
109 // Grab patch type and name
110 cfxFile >> cfxPatchTypes[patchI] >> cfxPatchNames[patchI] >> no;
113 patchRanges[patchI].setSize(6);
114 labelList& curRange = patchRanges[patchI];
118 cfxFile >> curRange[rI];
121 // Grab patch direction and master block ID
122 // Note: direc is the direction, from the cfx manual
123 // 0 = solid (3-D patch),
124 // 1 = high i, 2 = high j, 3 = high k
125 // 4 = low i, 5 = low j, 6 = low k
126 cfxFile >> patchDirections[patchI] >> blkNo >> patchLabel;
128 patchMasterBlocks[patchI] = blkNo - 1;
132 Info<< "Reading block glueing information" << endl;
134 labelList glueMasterPatches(nglue, -1);
135 labelList glueSlavePatches(nglue, -1);
138 label masterPatch, slavePatch;
139 label dirIndex1, dirIndex2, dirIndex3, joinNumber;
141 for (label glueI = 0; glueI < nglue; glueI++)
143 cfxFile >> masterPatch >> slavePatch;
144 cfxFile >> dirIndex1 >> dirIndex2 >> dirIndex3 >> joinNumber;
146 glueMasterPatches[glueI] = masterPatch - 1;
147 glueSlavePatches[glueI] = slavePatch - 1;
151 Info<< "Reading block points" << endl;
153 forAll(blocks, blockI)
155 Info<< "block " << blockI << " is a ";
156 blocks[blockI].readPoints(cfxFile);
159 Info<< "Calculating block offsets" << endl;
161 labelList blockOffsets(nblock, -1);
165 label nMeshPoints = blocks[0].nBlockPoints();
166 label nMeshCells = blocks[0].nBlockCells();
168 for (label blockI = 1; blockI < nblock; blockI++)
170 nMeshPoints += blocks[blockI].nBlockPoints();
171 nMeshCells += blocks[blockI].nBlockCells();
173 blockOffsets[blockI] =
174 blockOffsets[blockI - 1]
175 + blocks[blockI - 1].nBlockPoints();
178 Info<< "Assembling patches" << endl;
180 faceListList rawPatches(npatch);
182 forAll(rawPatches, patchI)
184 const word& patchType = cfxPatchTypes[patchI];
186 // reject volume patches
189 patchType == "POROUS" || patchType == "SOLID"
190 || patchType == "SOLCON" || patchType == "USER3D"
193 patchMasterBlocks[patchI] = -1;
194 rawPatches[patchI].setSize(0);
198 // read and create a 2-D patch
200 blocks[patchMasterBlocks[patchI]].patchFaces
202 patchDirections[patchI],
209 Info<< "Merging points ";
211 labelList pointMergeList(nMeshPoints, -1);
213 // In order to ensure robust merging, it is necessary to traverse
214 // the patch glueing list until the pointMergeList stops changing.
217 // For efficiency, create merge pairs in the first pass
218 labelListListList glueMergePairs(glueMasterPatches.size());
220 forAll(glueMasterPatches, glueI)
222 const label masterPatch = glueMasterPatches[glueI];
223 const label slavePatch = glueSlavePatches[glueI];
225 const label blockPlabel = patchMasterBlocks[masterPatch];
226 const label blockNlabel = patchMasterBlocks[slavePatch];
228 const pointField& blockPpoints = blocks[blockPlabel].points();
229 const pointField& blockNpoints = blocks[blockNlabel].points();
231 const faceList& blockPFaces = rawPatches[masterPatch];
232 const faceList& blockNFaces = rawPatches[slavePatch];
234 labelListList& curPairs = glueMergePairs[glueI];
235 curPairs.setSize(blockPFaces.size());
237 if (blockPFaces.size() != blockNFaces.size())
239 FatalErrorIn(args.executable())
240 << "Inconsistent number of faces for glue pair "
241 << glueI << " between blocks " << blockPlabel + 1
242 << " and " << blockNlabel + 1
243 << abort(FatalError);
246 // Calculate sqr of the merge tolerance as 1/10th of the min
247 // sqr point to point distance on the block face. This is an
248 // N^2 algorithm, sorry but I cannot quickly come up with
251 scalar sqrMergeTol = GREAT;
253 forAll(blockPFaces, blockPFaceLabel)
255 const labelList& blockPFacePoints =
256 blockPFaces[blockPFaceLabel];
258 forAll(blockPFacePoints, blockPFacePointI)
260 forAll(blockPFacePoints, blockPFacePointI2)
262 if (blockPFacePointI != blockPFacePointI2)
271 [blockPFacePoints[blockPFacePointI]]
273 [blockPFacePoints[blockPFacePointI2]]
283 register bool found = false;
285 // N-squared point search over all points of all faces of
286 // master block over all point of all faces of slave block
287 forAll(blockPFaces, blockPFaceLabel)
289 const labelList& blockPFacePoints =
290 blockPFaces[blockPFaceLabel];
292 labelList& cp = curPairs[blockPFaceLabel];
293 cp.setSize(blockPFacePoints.size());
295 forAll(blockPFacePoints, blockPFacePointI)
299 forAll(blockNFaces, blockNFaceLabel)
301 const labelList& blockNFacePoints =
302 blockNFaces[blockNFaceLabel];
304 forAll(blockNFacePoints, blockNFacePointI)
311 [blockPFacePoints[blockPFacePointI]]
313 [blockNFacePoints[blockNFacePointI]]
321 cp[blockPFacePointI] =
322 blockNFacePoints[blockNFacePointI];
325 blockPFacePoints[blockPFacePointI]
326 + blockOffsets[blockPlabel];
329 blockNFacePoints[blockNFacePointI]
330 + blockOffsets[blockNlabel];
332 label minPN = min(PpointLabel, NpointLabel);
334 if (pointMergeList[PpointLabel] != -1)
336 minPN = min(minPN, pointMergeList[PpointLabel]);
339 if (pointMergeList[NpointLabel] != -1)
341 minPN = min(minPN, pointMergeList[NpointLabel]);
344 pointMergeList[PpointLabel]
345 = pointMergeList[NpointLabel]
358 register bool changedPointMerge = false;
363 changedPointMerge = false;
366 forAll(glueMasterPatches, glueI)
368 const label masterPatch = glueMasterPatches[glueI];
369 const label slavePatch = glueSlavePatches[glueI];
371 const label blockPlabel = patchMasterBlocks[masterPatch];
372 const label blockNlabel = patchMasterBlocks[slavePatch];
374 const faceList& blockPFaces = rawPatches[masterPatch];
376 const labelListList& curPairs = glueMergePairs[glueI];
378 forAll(blockPFaces, blockPFaceLabel)
380 const labelList& blockPFacePoints =
381 blockPFaces[blockPFaceLabel];
383 const labelList& cp = curPairs[blockPFaceLabel];
385 forAll(cp, blockPFacePointI)
388 blockPFacePoints[blockPFacePointI]
389 + blockOffsets[blockPlabel];
393 + blockOffsets[blockNlabel];
397 pointMergeList[PpointLabel]
398 != pointMergeList[NpointLabel]
401 changedPointMerge = true;
403 pointMergeList[PpointLabel]
404 = pointMergeList[NpointLabel]
407 pointMergeList[PpointLabel],
408 pointMergeList[NpointLabel]
416 while (changedPointMerge && nPasses < 8);
419 if (changedPointMerge == true)
421 FatalErrorIn(args.executable())
422 << "Point merging failed after max number of passes."
423 << abort(FatalError);
427 forAll(glueMasterPatches, glueI)
429 const label masterPatch = glueMasterPatches[glueI];
430 const label slavePatch = glueSlavePatches[glueI];
432 const label blockPlabel = patchMasterBlocks[masterPatch];
433 const label blockNlabel = patchMasterBlocks[slavePatch];
435 const faceList& blockPFaces = rawPatches[masterPatch];
436 const faceList& blockNFaces = rawPatches[slavePatch];
439 forAll(blockPFaces, blockPFaceLabel)
441 const labelList& blockPFacePoints
442 = blockPFaces[blockPFaceLabel];
444 forAll(blockPFacePoints, blockPFacePointI)
447 blockPFacePoints[blockPFacePointI]
448 + blockOffsets[blockPlabel];
450 if (pointMergeList[PpointLabel] == -1)
452 FatalErrorIn(args.executable())
453 << "Unable to merge point " << blockPFacePointI
454 << " of face " << blockPFaceLabel
455 << " of block " << blockPlabel
456 << abort(FatalError);
461 forAll(blockNFaces, blockNFaceLabel)
463 const labelList& blockNFacePoints
464 = blockNFaces[blockNFaceLabel];
466 forAll(blockNFacePoints, blockNFacePointI)
469 blockNFacePoints[blockNFacePointI]
470 + blockOffsets[blockNlabel];
472 if (pointMergeList[NpointLabel] == -1)
474 FatalErrorIn(args.executable())
475 << "Unable to merge point " << blockNFacePointI
476 << " of face " << blockNFaceLabel
477 << " of block " << blockNlabel
478 << abort(FatalError);
485 // sort merge list to return new point label (in new shorter list)
486 // given old point label
487 label nNewPoints = 0;
489 forAll(pointMergeList, pointLabel)
491 if (pointMergeList[pointLabel] > pointLabel)
493 FatalErrorIn(args.executable())
494 << "ouch" << abort(FatalError);
499 (pointMergeList[pointLabel] == -1)
500 || pointMergeList[pointLabel] == pointLabel
503 pointMergeList[pointLabel] = nNewPoints;
508 pointMergeList[pointLabel] =
509 pointMergeList[pointMergeList[pointLabel]];
513 nMeshPoints = nNewPoints;
515 Info<< "Creating points" << endl;
517 pointField points(nMeshPoints);
519 forAll(blocks, blockI)
521 const pointField& blockPoints = blocks[blockI].points();
523 forAll(blockPoints, blockPointLabel)
530 + blockOffsets[blockI]
532 ] = blockPoints[blockPointLabel];
537 if (scaleFactor > 1.0 + SMALL || scaleFactor < 1.0 - SMALL)
539 points *= scaleFactor;
542 Info<< "Creating cells" << endl;
544 cellShapeList cellShapes(nMeshCells);
546 const cellModel& hex = *(cellModeller::lookup("hex"));
548 label nCreatedCells = 0;
550 forAll(blocks, blockI)
552 labelListList curBlockCells = blocks[blockI].blockCells();
554 forAll(curBlockCells, blockCellI)
556 labelList cellPoints(curBlockCells[blockCellI].size());
558 forAll(cellPoints, pointI)
563 curBlockCells[blockCellI][pointI]
564 + blockOffsets[blockI]
568 cellShapes[nCreatedCells] = cellShape(hex, cellPoints);
574 Info<< "Creating boundary patches" << endl;
576 faceListList boundary(npatch);
577 wordList patchNames(npatch);
578 wordList patchTypes(npatch);
579 word defaultFacesName = "defaultFaces";
580 word defaultFacesType = wallPolyPatch::typeName;
582 label nCreatedPatches = 0;
584 forAll(rawPatches, patchI)
586 if (rawPatches[patchI].size() && cfxPatchTypes[patchI] != "BLKBDY")
588 // Check if this name has been already created
589 label existingPatch = -1;
591 for (label oldPatchI = 0; oldPatchI < nCreatedPatches; oldPatchI++)
593 if (patchNames[oldPatchI] == cfxPatchNames[patchI])
595 existingPatch = oldPatchI;
600 const faceList& curRawPatch = rawPatches[patchI];
601 label curBlock = patchMasterBlocks[patchI];
603 if (existingPatch >= 0)
605 Info<< "CFX patch " << patchI
606 << ", of type " << cfxPatchTypes[patchI]
607 << ", name " << cfxPatchNames[patchI]
608 << " already exists as OpenFOAM patch " << existingPatch
609 << ". Adding faces." << endl;
611 faceList& renumberedPatch = boundary[existingPatch];
612 label oldSize = renumberedPatch.size();
613 renumberedPatch.setSize(oldSize + curRawPatch.size());
615 forAll(curRawPatch, faceI)
617 const face& oldFace = curRawPatch[faceI];
619 face& newFace = renumberedPatch[oldSize + faceI];
620 newFace.setSize(oldFace.size());
622 forAll(oldFace, pointI)
628 + blockOffsets[curBlock]
635 // Real patch to be created
636 faceList& renumberedPatch = boundary[nCreatedPatches];
637 renumberedPatch.setSize(curRawPatch.size());
639 forAll(curRawPatch, faceI)
641 const face& oldFace = curRawPatch[faceI];
643 face& newFace = renumberedPatch[faceI];
644 newFace.setSize(oldFace.size());
646 forAll(oldFace, pointI)
652 + blockOffsets[curBlock]
657 Info<< "CFX patch " << patchI
658 << ", of type " << cfxPatchTypes[patchI]
659 << ", name " << cfxPatchNames[patchI]
660 << " converted into OpenFOAM patch " << nCreatedPatches
663 if (cfxPatchTypes[patchI] == "WALL")
665 Info<< "wall." << endl;
667 patchTypes[nCreatedPatches] = wallPolyPatch::typeName;
668 patchNames[nCreatedPatches] = cfxPatchNames[patchI];
671 else if (cfxPatchTypes[patchI] == "SYMMET")
673 Info<< "symmetryPlane." << endl;
675 patchTypes[nCreatedPatches] = symmetryPolyPatch::typeName;
676 patchNames[nCreatedPatches] = cfxPatchNames[patchI];
681 cfxPatchTypes[patchI] == "INLET"
682 || cfxPatchTypes[patchI] == "OUTLET"
683 || cfxPatchTypes[patchI] == "PRESS"
684 || cfxPatchTypes[patchI] == "CNDBDY"
685 || cfxPatchTypes[patchI] == "USER2D"
688 Info<< "generic." << endl;
690 patchTypes[nCreatedPatches] = polyPatch::typeName;
691 patchNames[nCreatedPatches] = cfxPatchNames[patchI];
696 FatalErrorIn(args.executable())
697 << "Unrecognised CFX patch type "
698 << cfxPatchTypes[patchI]
699 << abort(FatalError);
705 boundary.setSize(nCreatedPatches);
706 patchTypes.setSize(nCreatedPatches);
707 patchNames.setSize(nCreatedPatches);
709 PtrList<dictionary> patchDicts;
715 polyMesh::meshSubDir,
722 // Add information to dictionary
723 forAll(patchNames, patchI)
725 if (!patchDicts.set(patchI))
727 patchDicts.set(patchI, new dictionary());
729 // Add but not overwrite
730 patchDicts[patchI].add("type", patchTypes[patchI], false);
737 polyMesh::defaultRegion,
750 // Set the precision of the points data to 10
751 IOstream::defaultPrecision(10);
753 Info<< "Writing polyMesh" << endl;
756 Info<< "End\n" << endl;
762 // ************************************************************************* //