1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 Converts a CFX 4 mesh to FOAM format
31 \*---------------------------------------------------------------------------*/
38 #include "wallPolyPatch.H"
39 #include "symmetryPolyPatch.H"
40 #include "preservePatchTypes.H"
41 #include "cellShape.H"
42 #include "cellModeller.H"
46 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
49 int main(int argc, char *argv[])
51 argList::noParallel();
52 argList::validArgs.append("CFX geom file");
53 argList::validOptions.insert("scale", "scale factor");
55 argList args(argc, argv);
62 scalar scaleFactor = 1.0;
63 args.optionReadIfPresent("scale", scaleFactor);
65 # include "createTime.H"
67 IFstream cfxFile(args.additionalArgs()[0]);
69 // Read the cfx information using a fixed format reader.
70 // Comments in the file are in C++ style, so the stream parser will remove
71 // them with no intervention
72 label nblock, npatch, nglue, nelem, npoint;
74 cfxFile >> nblock >> npatch >> nglue >> nelem >> npoint;
76 Info << "Reading blocks" << endl;
78 PtrList<hexBlock> blocks(nblock);
84 forAll (blocks, blockI)
87 cfxFile >> nx >> ny >> nz;
89 blocks.set(blockI, new hexBlock(nx, ny, nz));
93 Info << "Reading patch definitions" << endl;
95 wordList cfxPatchTypes(npatch);
96 wordList cfxPatchNames(npatch);
97 labelList patchMasterBlocks(npatch);
98 labelList patchDirections(npatch);
99 labelListList patchRanges(npatch);
102 label no, blkNo, patchLabel;
104 forAll (cfxPatchTypes, patchI)
106 // Grab patch type and name
107 cfxFile >> cfxPatchTypes[patchI] >> cfxPatchNames[patchI] >> no;
110 patchRanges[patchI].setSize(6);
111 labelList& curRange = patchRanges[patchI];
113 forAll (curRange, rI)
115 cfxFile >> curRange[rI];
118 // Grab patch direction and master block ID
119 // Note: direc is the direction, from the cfx manual
120 // 0 = solid (3-D patch),
121 // 1 = high i, 2 = high j, 3 = high k
122 // 4 = low i, 5 = low j, 6 = low k
123 cfxFile >> patchDirections[patchI] >> blkNo >> patchLabel;
125 patchMasterBlocks[patchI] = blkNo - 1;
129 Info << "Reading block glueing information" << endl;
131 labelList glueMasterPatches(nglue, -1);
132 labelList glueSlavePatches(nglue, -1);
135 label masterPatch, slavePatch;
136 label dirIndex1, dirIndex2, dirIndex3, joinNumber;
138 for (label glueI = 0; glueI < nglue; glueI++)
140 cfxFile >> masterPatch >> slavePatch;
141 cfxFile >> dirIndex1 >> dirIndex2 >> dirIndex3 >> joinNumber;
143 glueMasterPatches[glueI] = masterPatch - 1;
144 glueSlavePatches[glueI] = slavePatch - 1;
148 Info << "Reading block points" << endl;
150 forAll (blocks, blockI)
152 Info << "block " << blockI << " is a ";
153 blocks[blockI].readPoints(cfxFile);
156 Info << "Calculating block offsets" << endl;
158 labelList blockOffsets(nblock, -1);
162 label nMeshPoints = blocks[0].nBlockPoints();
163 label nMeshCells = blocks[0].nBlockCells();
165 for (label blockI = 1; blockI < nblock; blockI++)
167 nMeshPoints += blocks[blockI].nBlockPoints();
168 nMeshCells += blocks[blockI].nBlockCells();
170 blockOffsets[blockI] =
171 blockOffsets[blockI - 1]
172 + blocks[blockI - 1].nBlockPoints();
175 Info << "Assembling patches" << endl;
177 faceListList rawPatches(npatch);
179 forAll (rawPatches, patchI)
181 const word& patchType = cfxPatchTypes[patchI];
183 // reject volume patches
186 patchType == "POROUS" || patchType == "SOLID"
187 || patchType == "SOLCON" || patchType == "USER3D"
190 patchMasterBlocks[patchI] = -1;
191 rawPatches[patchI].setSize(0);
195 // read and create a 2-D patch
197 blocks[patchMasterBlocks[patchI]].patchFaces
199 patchDirections[patchI],
206 Info << "Merging points ";
208 labelList pointMergeList(nMeshPoints, -1);
210 // In order to ensure robust merging, it is necessary to traverse
211 // the patch glueing list until the pointMergeList stops changing.
214 // For efficiency, create merge pairs in the first pass
215 labelListListList glueMergePairs(glueMasterPatches.size());
217 forAll (glueMasterPatches, glueI)
219 const label masterPatch = glueMasterPatches[glueI];
220 const label slavePatch = glueSlavePatches[glueI];
222 const label blockPlabel = patchMasterBlocks[masterPatch];
223 const label blockNlabel = patchMasterBlocks[slavePatch];
225 const pointField& blockPpoints = blocks[blockPlabel].points();
226 const pointField& blockNpoints = blocks[blockNlabel].points();
228 const faceList& blockPFaces = rawPatches[masterPatch];
229 const faceList& blockNFaces = rawPatches[slavePatch];
231 labelListList& curPairs = glueMergePairs[glueI];
232 curPairs.setSize(blockPFaces.size());
234 if (blockPFaces.size() != blockNFaces.size())
236 FatalErrorIn(args.executable())
237 << "Inconsistent number of faces for glue pair "
238 << glueI << " between blocks " << blockPlabel + 1
239 << " and " << blockNlabel + 1
240 << abort(FatalError);
243 // Calculate sqr of the merge tolerance as 1/10th of the min
244 // sqr point to point distance on the block face. This is an
245 // N^2 algorithm, sorry but I cannot quickly come up with
248 scalar sqrMergeTol = GREAT;
250 forAll (blockPFaces, blockPFaceLabel)
252 const labelList& blockPFacePoints =
253 blockPFaces[blockPFaceLabel];
255 forAll (blockPFacePoints, blockPFacePointI)
257 forAll (blockPFacePoints, blockPFacePointI2)
259 if (blockPFacePointI != blockPFacePointI2)
268 [blockPFacePoints[blockPFacePointI]]
270 [blockPFacePoints[blockPFacePointI2]]
280 register bool found = false;
282 // N-squared point search over all points of all faces of
283 // master block over all point of all faces of slave block
284 forAll (blockPFaces, blockPFaceLabel)
286 const labelList& blockPFacePoints =
287 blockPFaces[blockPFaceLabel];
289 labelList& cp = curPairs[blockPFaceLabel];
290 cp.setSize(blockPFacePoints.size());
292 forAll (blockPFacePoints, blockPFacePointI)
296 forAll (blockNFaces, blockNFaceLabel)
298 const labelList& blockNFacePoints =
299 blockNFaces[blockNFaceLabel];
301 forAll (blockNFacePoints, blockNFacePointI)
308 [blockPFacePoints[blockPFacePointI]]
310 [blockNFacePoints[blockNFacePointI]]
318 cp[blockPFacePointI] =
319 blockNFacePoints[blockNFacePointI];
322 blockPFacePoints[blockPFacePointI]
323 + blockOffsets[blockPlabel];
326 blockNFacePoints[blockNFacePointI]
327 + blockOffsets[blockNlabel];
329 label minPN = min(PpointLabel, NpointLabel);
331 if (pointMergeList[PpointLabel] != -1)
333 minPN = min(minPN, pointMergeList[PpointLabel]);
336 if (pointMergeList[NpointLabel] != -1)
338 minPN = min(minPN, pointMergeList[NpointLabel]);
341 pointMergeList[PpointLabel]
342 = pointMergeList[NpointLabel]
355 register bool changedPointMerge = false;
360 changedPointMerge = false;
363 forAll (glueMasterPatches, glueI)
365 const label masterPatch = glueMasterPatches[glueI];
366 const label slavePatch = glueSlavePatches[glueI];
368 const label blockPlabel = patchMasterBlocks[masterPatch];
369 const label blockNlabel = patchMasterBlocks[slavePatch];
371 const faceList& blockPFaces = rawPatches[masterPatch];
373 const labelListList& curPairs = glueMergePairs[glueI];
375 forAll (blockPFaces, blockPFaceLabel)
377 const labelList& blockPFacePoints =
378 blockPFaces[blockPFaceLabel];
380 const labelList& cp = curPairs[blockPFaceLabel];
382 forAll (cp, blockPFacePointI)
385 blockPFacePoints[blockPFacePointI]
386 + blockOffsets[blockPlabel];
390 + blockOffsets[blockNlabel];
394 pointMergeList[PpointLabel]
395 != pointMergeList[NpointLabel]
398 changedPointMerge = true;
400 pointMergeList[PpointLabel]
401 = pointMergeList[NpointLabel]
404 pointMergeList[PpointLabel],
405 pointMergeList[NpointLabel]
411 Info << "." << flush;
413 while (changedPointMerge && nPasses < 8);
416 if (changedPointMerge == true)
418 FatalErrorIn(args.executable())
419 << "Point merging failed after max number of passes."
420 << abort(FatalError);
424 forAll (glueMasterPatches, glueI)
426 const label masterPatch = glueMasterPatches[glueI];
427 const label slavePatch = glueSlavePatches[glueI];
429 const label blockPlabel = patchMasterBlocks[masterPatch];
430 const label blockNlabel = patchMasterBlocks[slavePatch];
432 const faceList& blockPFaces = rawPatches[masterPatch];
433 const faceList& blockNFaces = rawPatches[slavePatch];
436 forAll (blockPFaces, blockPFaceLabel)
438 const labelList& blockPFacePoints
439 = blockPFaces[blockPFaceLabel];
441 forAll (blockPFacePoints, blockPFacePointI)
444 blockPFacePoints[blockPFacePointI]
445 + blockOffsets[blockPlabel];
447 if (pointMergeList[PpointLabel] == -1)
449 FatalErrorIn(args.executable())
450 << "Unable to merge point " << blockPFacePointI
451 << " of face " << blockPFaceLabel
452 << " of block " << blockPlabel
453 << abort(FatalError);
458 forAll (blockNFaces, blockNFaceLabel)
460 const labelList& blockNFacePoints
461 = blockNFaces[blockNFaceLabel];
463 forAll (blockNFacePoints, blockNFacePointI)
466 blockNFacePoints[blockNFacePointI]
467 + blockOffsets[blockNlabel];
469 if (pointMergeList[NpointLabel] == -1)
471 FatalErrorIn(args.executable())
472 << "Unable to merge point " << blockNFacePointI
473 << " of face " << blockNFaceLabel
474 << " of block " << blockNlabel
475 << abort(FatalError);
482 // sort merge list to return new point label (in new shorter list)
483 // given old point label
484 label nNewPoints = 0;
486 forAll (pointMergeList, pointLabel)
488 if (pointMergeList[pointLabel] > pointLabel)
490 FatalErrorIn(args.executable())
491 << "ouch" << abort(FatalError);
496 (pointMergeList[pointLabel] == -1)
497 || pointMergeList[pointLabel] == pointLabel
500 pointMergeList[pointLabel] = nNewPoints;
505 pointMergeList[pointLabel] =
506 pointMergeList[pointMergeList[pointLabel]];
510 nMeshPoints = nNewPoints;
512 Info << "Creating points" << endl;
514 pointField points(nMeshPoints);
516 forAll (blocks, blockI)
518 const pointField& blockPoints = blocks[blockI].points();
520 forAll (blockPoints, blockPointLabel)
527 + blockOffsets[blockI]
529 ] = blockPoints[blockPointLabel];
534 if (scaleFactor > 1.0 + SMALL || scaleFactor < 1.0 - SMALL)
536 points *= scaleFactor;
539 Info << "Creating cells" << endl;
541 cellShapeList cellShapes(nMeshCells);
543 const cellModel& hex = *(cellModeller::lookup("hex"));
545 label nCreatedCells = 0;
547 forAll (blocks, blockI)
549 labelListList curBlockCells = blocks[blockI].blockCells();
551 forAll (curBlockCells, blockCellI)
553 labelList cellPoints(curBlockCells[blockCellI].size());
555 forAll (cellPoints, pointI)
560 curBlockCells[blockCellI][pointI]
561 + blockOffsets[blockI]
565 cellShapes[nCreatedCells] = cellShape(hex, cellPoints);
571 Info << "Creating boundary patches" << endl;
573 faceListList boundary(npatch);
574 wordList patchNames(npatch);
575 wordList patchTypes(npatch);
576 word defaultFacesName = "defaultFaces";
577 word defaultFacesType = wallPolyPatch::typeName;
578 wordList patchPhysicalTypes(npatch);
580 label nCreatedPatches = 0;
582 forAll (rawPatches, patchI)
584 if (rawPatches[patchI].size() && cfxPatchTypes[patchI] != "BLKBDY")
586 // Check if this name has been already created
587 label existingPatch = -1;
589 for (label oldPatchI = 0; oldPatchI < nCreatedPatches; oldPatchI++)
591 if (patchNames[oldPatchI] == cfxPatchNames[patchI])
593 existingPatch = oldPatchI;
598 const faceList& curRawPatch = rawPatches[patchI];
599 label curBlock = patchMasterBlocks[patchI];
601 if (existingPatch >= 0)
603 Info << "CFX patch " << patchI
604 << ", of type " << cfxPatchTypes[patchI]
605 << ", name " << cfxPatchNames[patchI]
606 << " already exists as FOAM patch " << existingPatch
607 << ". Adding faces." << endl;
609 faceList& renumberedPatch = boundary[existingPatch];
610 label oldSize = renumberedPatch.size();
611 renumberedPatch.setSize(oldSize + curRawPatch.size());
613 forAll (curRawPatch, faceI)
615 const face& oldFace = curRawPatch[faceI];
617 face& newFace = renumberedPatch[oldSize + faceI];
618 newFace.setSize(oldFace.size());
620 forAll (oldFace, pointI)
626 + blockOffsets[curBlock]
633 // Real patch to be created
634 faceList& renumberedPatch = boundary[nCreatedPatches];
635 renumberedPatch.setSize(curRawPatch.size());
637 forAll (curRawPatch, faceI)
639 const face& oldFace = curRawPatch[faceI];
641 face& newFace = renumberedPatch[faceI];
642 newFace.setSize(oldFace.size());
644 forAll (oldFace, pointI)
650 + blockOffsets[curBlock]
655 Info << "CFX patch " << patchI
656 << ", of type " << cfxPatchTypes[patchI]
657 << ", name " << cfxPatchNames[patchI]
658 << " converted into FOAM patch " << nCreatedPatches
661 if (cfxPatchTypes[patchI] == "WALL")
663 Info << "wall." << endl;
665 patchTypes[nCreatedPatches] = wallPolyPatch::typeName;
666 patchNames[nCreatedPatches] = cfxPatchNames[patchI];
669 else if (cfxPatchTypes[patchI] == "SYMMET")
671 Info << "symmetryPlane." << endl;
673 patchTypes[nCreatedPatches] = symmetryPolyPatch::typeName;
674 patchNames[nCreatedPatches] = cfxPatchNames[patchI];
679 cfxPatchTypes[patchI] == "INLET"
680 || cfxPatchTypes[patchI] == "OUTLET"
681 || cfxPatchTypes[patchI] == "PRESS"
682 || cfxPatchTypes[patchI] == "CNDBDY"
683 || cfxPatchTypes[patchI] == "USER2D"
686 Info << "generic." << endl;
688 patchTypes[nCreatedPatches] = polyPatch::typeName;
689 patchNames[nCreatedPatches] = cfxPatchNames[patchI];
694 FatalErrorIn(args.executable())
695 << "Unrecognised CFX patch type "
696 << cfxPatchTypes[patchI]
697 << abort(FatalError);
703 boundary.setSize(nCreatedPatches);
704 patchTypes.setSize(nCreatedPatches);
705 patchNames.setSize(nCreatedPatches);
711 polyMesh::defaultRegion,
723 polyMesh::defaultRegion,
737 // Set the precision of the points data to 10
738 IOstream::defaultPrecision(10);
740 Info << "Writing polyMesh" << endl;
743 Info << "End\n" << endl;
749 // ************************************************************************* //