ENH: autoLayerDriver: better layering information message
[OpenFOAM-2.0.x.git] / applications / utilities / mesh / conversion / cfx4ToFoam / cfx4ToFoam.C
blob2d209691e22ec824507905169b320345de5a2871
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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/>.
24 Application
25     cfx4ToFoam
27 Description
28     Converts a CFX 4 mesh to OpenFOAM format
30 \*---------------------------------------------------------------------------*/
32 #include "argList.H"
33 #include "Time.H"
34 #include "IFstream.H"
35 #include "hexBlock.H"
36 #include "polyMesh.H"
37 #include "wallPolyPatch.H"
38 #include "symmetryPolyPatch.H"
39 #include "preservePatchTypes.H"
40 #include "cellShape.H"
41 #include "cellModeller.H"
43 using namespace Foam;
45 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 // Main program:
48 int main(int argc, char *argv[])
50     argList::noParallel();
51     argList::validArgs.append("CFX geom file");
52     argList::addOption
53     (
54         "scale",
55         "factor",
56         "geometry scaling factor - default is 1"
57     );
59     argList args(argc, argv);
61     if (!args.check())
62     {
63          FatalError.exit();
64     }
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);
83     {
84         word blockName;
85         label nx, ny, nz;
87         forAll(blocks, blockI)
88         {
89             cfxFile >> blockName;
90             cfxFile >> nx >> ny >> nz;
92             blocks.set(blockI, new hexBlock(nx, ny, nz));
93         }
94     }
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);
104     {
105         label no, blkNo, patchLabel;
107         forAll(cfxPatchTypes, patchI)
108         {
109             // Grab patch type and name
110             cfxFile >> cfxPatchTypes[patchI] >> cfxPatchNames[patchI] >> no;
112             // Grab patch range
113             patchRanges[patchI].setSize(6);
114             labelList& curRange = patchRanges[patchI];
116             forAll(curRange, rI)
117             {
118                 cfxFile >> curRange[rI];
119             }
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;
129         }
130     }
132     Info<< "Reading block glueing information" << endl;
134     labelList glueMasterPatches(nglue, -1);
135     labelList glueSlavePatches(nglue, -1);
137     {
138         label masterPatch, slavePatch;
139         label dirIndex1, dirIndex2, dirIndex3, joinNumber;
141         for (label glueI = 0; glueI < nglue; glueI++)
142         {
143             cfxFile >> masterPatch >> slavePatch;
144             cfxFile >> dirIndex1 >> dirIndex2 >> dirIndex3 >> joinNumber;
146             glueMasterPatches[glueI] = masterPatch - 1;
147             glueSlavePatches[glueI] = slavePatch - 1;
148         }
149     }
151     Info<< "Reading block points" << endl;
153     forAll(blocks, blockI)
154     {
155         Info<< "block " << blockI << " is a ";
156         blocks[blockI].readPoints(cfxFile);
157     }
159     Info<< "Calculating block offsets" << endl;
161     labelList blockOffsets(nblock, -1);
163     blockOffsets[0] = 0;
165     label nMeshPoints = blocks[0].nBlockPoints();
166     label nMeshCells = blocks[0].nBlockCells();
168     for (label blockI = 1; blockI < nblock; blockI++)
169     {
170         nMeshPoints += blocks[blockI].nBlockPoints();
171         nMeshCells +=  blocks[blockI].nBlockCells();
173         blockOffsets[blockI] =
174             blockOffsets[blockI - 1]
175           + blocks[blockI - 1].nBlockPoints();
176     }
178     Info<< "Assembling patches" << endl;
180     faceListList rawPatches(npatch);
182     forAll(rawPatches, patchI)
183     {
184         const word& patchType = cfxPatchTypes[patchI];
186         // reject volume patches
187         if
188         (
189             patchType == "POROUS" || patchType == "SOLID"
190          || patchType == "SOLCON" || patchType == "USER3D"
191         )
192         {
193             patchMasterBlocks[patchI] = -1;
194             rawPatches[patchI].setSize(0);
195         }
196         else
197         {
198             // read and create a 2-D patch
199             rawPatches[patchI] =
200                 blocks[patchMasterBlocks[patchI]].patchFaces
201                 (
202                     patchDirections[patchI],
203                     patchRanges[patchI]
204                 );
206         }
207     }
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.
215     //
217     // For efficiency, create merge pairs in the first pass
218     labelListListList glueMergePairs(glueMasterPatches.size());
220     forAll(glueMasterPatches, glueI)
221     {
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())
238         {
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);
244         }
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
249         // something better.
251         scalar sqrMergeTol = GREAT;
253         forAll(blockPFaces, blockPFaceLabel)
254         {
255             const labelList& blockPFacePoints =
256                 blockPFaces[blockPFaceLabel];
258             forAll(blockPFacePoints, blockPFacePointI)
259             {
260                 forAll(blockPFacePoints, blockPFacePointI2)
261                 {
262                     if (blockPFacePointI != blockPFacePointI2)
263                     {
264                         sqrMergeTol =
265                             min
266                             (
267                                 sqrMergeTol,
268                                 magSqr
269                                 (
270                                     blockPpoints
271                                         [blockPFacePoints[blockPFacePointI]]
272                                   - blockPpoints
273                                         [blockPFacePoints[blockPFacePointI2]]
274                                 )
275                             );
276                     }
277                 }
278             }
279         }
281         sqrMergeTol /= 10.0;
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)
288         {
289             const labelList& blockPFacePoints =
290                 blockPFaces[blockPFaceLabel];
292             labelList& cp = curPairs[blockPFaceLabel];
293             cp.setSize(blockPFacePoints.size());
295         forAll(blockPFacePoints, blockPFacePointI)
296         {
297             found = false;
299             forAll(blockNFaces, blockNFaceLabel)
300             {
301                 const labelList& blockNFacePoints =
302                     blockNFaces[blockNFaceLabel];
304             forAll(blockNFacePoints, blockNFacePointI)
305             {
306                 if
307                 (
308                     magSqr
309                     (
310                         blockPpoints
311                             [blockPFacePoints[blockPFacePointI]]
312                       - blockNpoints
313                             [blockNFacePoints[blockNFacePointI]]
314                     )
315                   < sqrMergeTol
316                 )
317                 {
318                     // Found a new pair
319                     found = true;
321                     cp[blockPFacePointI] =
322                         blockNFacePoints[blockNFacePointI];
324                     label PpointLabel =
325                         blockPFacePoints[blockPFacePointI]
326                       + blockOffsets[blockPlabel];
328                     label NpointLabel =
329                         blockNFacePoints[blockNFacePointI]
330                       + blockOffsets[blockNlabel];
332                     label minPN = min(PpointLabel, NpointLabel);
334                     if (pointMergeList[PpointLabel] != -1)
335                     {
336                         minPN = min(minPN, pointMergeList[PpointLabel]);
337                     }
339                     if (pointMergeList[NpointLabel] != -1)
340                     {
341                         minPN = min(minPN, pointMergeList[NpointLabel]);
342                     }
344                     pointMergeList[PpointLabel]
345                   = pointMergeList[NpointLabel]
346                   = minPN;
348                     break;
349                 }
350             }
351             if (found) break;
352             }
353         }
354         }
355     }
358     register bool changedPointMerge = false;
359     label nPasses = 0;
361     do
362     {
363         changedPointMerge = false;
364         nPasses++;
366         forAll(glueMasterPatches, glueI)
367         {
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)
379             {
380                 const labelList& blockPFacePoints =
381                     blockPFaces[blockPFaceLabel];
383                 const labelList& cp = curPairs[blockPFaceLabel];
385                 forAll(cp, blockPFacePointI)
386                 {
387                     label PpointLabel =
388                         blockPFacePoints[blockPFacePointI]
389                       + blockOffsets[blockPlabel];
391                     label NpointLabel =
392                         cp[blockPFacePointI]
393                       + blockOffsets[blockNlabel];
395                     if
396                     (
397                         pointMergeList[PpointLabel]
398                      != pointMergeList[NpointLabel]
399                     )
400                     {
401                         changedPointMerge = true;
403                         pointMergeList[PpointLabel]
404                       = pointMergeList[NpointLabel]
405                       = min
406                         (
407                             pointMergeList[PpointLabel],
408                             pointMergeList[NpointLabel]
409                         );
410                     }
411                 }
412             }
413         }
414         Info<< "." << flush;
415     }
416     while (changedPointMerge && nPasses < 8);
417     Info<< endl;
419     if (changedPointMerge == true)
420     {
421         FatalErrorIn(args.executable())
422             << "Point merging failed after max number of passes."
423             << abort(FatalError);
424     }
427     forAll(glueMasterPatches, glueI)
428     {
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)
440         {
441             const labelList& blockPFacePoints
442                 = blockPFaces[blockPFaceLabel];
444             forAll(blockPFacePoints, blockPFacePointI)
445             {
446                 label PpointLabel =
447                     blockPFacePoints[blockPFacePointI]
448                   + blockOffsets[blockPlabel];
450                 if (pointMergeList[PpointLabel] == -1)
451                 {
452                     FatalErrorIn(args.executable())
453                         << "Unable to merge point " << blockPFacePointI
454                         << " of face " << blockPFaceLabel
455                         << " of block " << blockPlabel
456                         << abort(FatalError);
457                 }
458             }
459         }
461         forAll(blockNFaces, blockNFaceLabel)
462         {
463             const labelList& blockNFacePoints
464                 = blockNFaces[blockNFaceLabel];
466             forAll(blockNFacePoints, blockNFacePointI)
467             {
468                 label NpointLabel =
469                     blockNFacePoints[blockNFacePointI]
470                   + blockOffsets[blockNlabel];
472                 if (pointMergeList[NpointLabel] == -1)
473                 {
474                     FatalErrorIn(args.executable())
475                         << "Unable to merge point " << blockNFacePointI
476                         << " of face " << blockNFaceLabel
477                         << " of block " << blockNlabel
478                         << abort(FatalError);
479                 }
480             }
481         }
482     }
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)
490     {
491         if (pointMergeList[pointLabel] > pointLabel)
492         {
493             FatalErrorIn(args.executable())
494                 << "ouch" << abort(FatalError);
495         }
497         if
498         (
499             (pointMergeList[pointLabel] == -1)
500          || pointMergeList[pointLabel] == pointLabel
501         )
502         {
503             pointMergeList[pointLabel] = nNewPoints;
504             nNewPoints++;
505         }
506         else
507         {
508             pointMergeList[pointLabel] =
509                 pointMergeList[pointMergeList[pointLabel]];
510         }
511     }
513     nMeshPoints = nNewPoints;
515     Info<< "Creating points" << endl;
517     pointField points(nMeshPoints);
519     forAll(blocks, blockI)
520     {
521         const pointField& blockPoints = blocks[blockI].points();
523         forAll(blockPoints, blockPointLabel)
524         {
525             points
526             [
527                 pointMergeList
528                 [
529                     blockPointLabel
530                   + blockOffsets[blockI]
531                 ]
532             ] = blockPoints[blockPointLabel];
533         }
534     }
536     // Scale the points
537     if (scaleFactor > 1.0 + SMALL || scaleFactor < 1.0 - SMALL)
538     {
539         points *= scaleFactor;
540     }
542     Info<< "Creating cells" << endl;
544     cellShapeList cellShapes(nMeshCells);
546     const cellModel& hex = *(cellModeller::lookup("hex"));
548     label nCreatedCells = 0;
550     forAll(blocks, blockI)
551     {
552         labelListList curBlockCells = blocks[blockI].blockCells();
554         forAll(curBlockCells, blockCellI)
555         {
556             labelList cellPoints(curBlockCells[blockCellI].size());
558             forAll(cellPoints, pointI)
559             {
560                 cellPoints[pointI] =
561                     pointMergeList
562                     [
563                         curBlockCells[blockCellI][pointI]
564                       + blockOffsets[blockI]
565                     ];
566             }
568             cellShapes[nCreatedCells] = cellShape(hex, cellPoints);
570             nCreatedCells++;
571         }
572     }
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)
585     {
586         if (rawPatches[patchI].size() && cfxPatchTypes[patchI] != "BLKBDY")
587         {
588             // Check if this name has been already created
589             label existingPatch = -1;
591             for (label oldPatchI = 0; oldPatchI < nCreatedPatches; oldPatchI++)
592             {
593                 if (patchNames[oldPatchI] == cfxPatchNames[patchI])
594                 {
595                     existingPatch = oldPatchI;
596                     break;
597                 }
598             }
600             const faceList& curRawPatch = rawPatches[patchI];
601             label curBlock = patchMasterBlocks[patchI];
603             if (existingPatch >= 0)
604             {
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)
616                 {
617                     const face& oldFace = curRawPatch[faceI];
619                     face& newFace = renumberedPatch[oldSize + faceI];
620                     newFace.setSize(oldFace.size());
622                     forAll(oldFace, pointI)
623                     {
624                         newFace[pointI] =
625                             pointMergeList
626                             [
627                                 oldFace[pointI]
628                               + blockOffsets[curBlock]
629                             ];
630                     }
631                 }
632             }
633             else
634             {
635                 // Real patch to be created
636                 faceList& renumberedPatch = boundary[nCreatedPatches];
637                 renumberedPatch.setSize(curRawPatch.size());
639                 forAll(curRawPatch, faceI)
640                 {
641                     const face& oldFace = curRawPatch[faceI];
643                     face& newFace = renumberedPatch[faceI];
644                     newFace.setSize(oldFace.size());
646                     forAll(oldFace, pointI)
647                     {
648                         newFace[pointI] =
649                             pointMergeList
650                             [
651                                 oldFace[pointI]
652                               + blockOffsets[curBlock]
653                             ];
654                     }
655                 }
657                 Info<< "CFX patch " << patchI
658                     << ", of type " << cfxPatchTypes[patchI]
659                     << ", name " << cfxPatchNames[patchI]
660                     << " converted into OpenFOAM patch " << nCreatedPatches
661                     << " type ";
663                 if (cfxPatchTypes[patchI] == "WALL")
664                 {
665                     Info<< "wall." << endl;
667                     patchTypes[nCreatedPatches] = wallPolyPatch::typeName;
668                     patchNames[nCreatedPatches] = cfxPatchNames[patchI];
669                     nCreatedPatches++;
670                 }
671                 else if (cfxPatchTypes[patchI] == "SYMMET")
672                 {
673                     Info<< "symmetryPlane." << endl;
675                     patchTypes[nCreatedPatches] = symmetryPolyPatch::typeName;
676                     patchNames[nCreatedPatches] = cfxPatchNames[patchI];
677                     nCreatedPatches++;
678                 }
679                 else if
680                 (
681                     cfxPatchTypes[patchI] == "INLET"
682                  || cfxPatchTypes[patchI] == "OUTLET"
683                  || cfxPatchTypes[patchI] == "PRESS"
684                  || cfxPatchTypes[patchI] == "CNDBDY"
685                  || cfxPatchTypes[patchI] == "USER2D"
686                 )
687                 {
688                     Info<< "generic." << endl;
690                     patchTypes[nCreatedPatches] = polyPatch::typeName;
691                     patchNames[nCreatedPatches] = cfxPatchNames[patchI];
692                     nCreatedPatches++;
693                 }
694                 else
695                 {
696                     FatalErrorIn(args.executable())
697                         << "Unrecognised CFX patch type "
698                         << cfxPatchTypes[patchI]
699                         << abort(FatalError);
700                 }
701             }
702         }
703     }
705     boundary.setSize(nCreatedPatches);
706     patchTypes.setSize(nCreatedPatches);
707     patchNames.setSize(nCreatedPatches);
709     PtrList<dictionary> patchDicts;
711     preservePatchTypes
712     (
713         runTime,
714         runTime.constant(),
715         polyMesh::meshSubDir,
716         patchNames,
717         patchDicts,
718         defaultFacesName,
719         defaultFacesType
720     );
722     // Add information to dictionary
723     forAll(patchNames, patchI)
724     {
725         if (!patchDicts.set(patchI))
726         {
727             patchDicts.set(patchI, new dictionary());
728         }
729         // Add but not overwrite
730         patchDicts[patchI].add("type", patchTypes[patchI], false);
731     }
733     polyMesh pShapeMesh
734     (
735         IOobject
736         (
737             polyMesh::defaultRegion,
738             runTime.constant(),
739             runTime
740         ),
741         xferMove(points),
742         cellShapes,
743         boundary,
744         patchNames,
745         patchDicts,
746         defaultFacesName,
747         defaultFacesType
748     );
750     // Set the precision of the points data to 10
751     IOstream::defaultPrecision(10);
753     Info<< "Writing polyMesh" << endl;
754     pShapeMesh.write();
756     Info<< "End\n" << endl;
758     return 0;
762 // ************************************************************************* //