00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 #include <OpenFOAM/argList.H>
00092 #include <OpenFOAM/Time.H>
00093 #include <OpenFOAM/polyMesh.H>
00094 #include <OpenFOAM/IFstream.H>
00095 #include <OpenFOAM/cellModeller.H>
00096
00097 using namespace Foam;
00098
00099
00100
00101
00102 label findFace(const primitiveMesh& mesh, const face& f)
00103 {
00104 const labelList& pFaces = mesh.pointFaces()[f[0]];
00105
00106 forAll(pFaces, i)
00107 {
00108 label faceI = pFaces[i];
00109
00110 if (mesh.faces()[faceI] == f)
00111 {
00112 return faceI;
00113 }
00114 }
00115
00116 FatalErrorIn("findFace(const primitiveMesh&, const face&)")
00117 << "Cannot find face " << f << " in mesh." << abort(FatalError);
00118
00119 return -1;
00120 }
00121
00122
00123
00124
00125 int main(int argc, char *argv[])
00126 {
00127 argList::validArgs.append("file prefix");
00128 argList::validOptions.insert("noFaceFile", "");
00129
00130 # include <OpenFOAM/setRootCase.H>
00131 # include <OpenFOAM/createTime.H>
00132
00133
00134 bool readFaceFile = !args.optionFound("noFaceFile");
00135
00136 fileName prefix(args.additionalArgs()[0]);
00137
00138 fileName nodeFile(prefix + ".node");
00139 fileName eleFile(prefix + ".ele");
00140 fileName faceFile(prefix + ".face");
00141
00142 if (!readFaceFile)
00143 {
00144 Info<< "Files:" << endl
00145 << " nodes : " << nodeFile << endl
00146 << " elems : " << eleFile << endl
00147 << endl;
00148 }
00149 else
00150 {
00151 Info<< "Files:" << endl
00152 << " nodes : " << nodeFile << endl
00153 << " elems : " << eleFile << endl
00154 << " faces : " << faceFile << endl
00155 << endl;
00156
00157 Info<< "Reading .face file for boundary information" << nl << endl;
00158 }
00159
00160 if (!isFile(nodeFile) || !isFile(eleFile))
00161 {
00162 FatalErrorIn(args.executable())
00163 << "Cannot read " << nodeFile << " or " << eleFile
00164 << exit(FatalError);
00165 }
00166
00167 if (readFaceFile && !isFile(faceFile))
00168 {
00169 FatalErrorIn(args.executable())
00170 << "Cannot read " << faceFile << endl
00171 << "Did you run tetgen with -f option?" << endl
00172 << "If you don't want to read the .face file and thus not have"
00173 << " patches please\nrerun with the -noFaceFile option"
00174 << exit(FatalError);
00175 }
00176
00177
00178 IFstream nodeStream(nodeFile);
00179
00180
00181
00182
00183
00184
00185 string line;
00186
00187 do
00188 {
00189 nodeStream.getLine(line);
00190 }
00191 while (line.size() && line[0] == '#');
00192
00193 IStringStream nodeLine(line);
00194
00195 label nNodes, nDims, nNodeAttr;
00196 bool hasRegion;
00197
00198 nodeLine >> nNodes >> nDims >> nNodeAttr >> hasRegion;
00199
00200
00201 Info<< "Read .node header:" << endl
00202 << " nodes : " << nNodes << endl
00203 << " nDims : " << nDims << endl
00204 << " nAttr : " << nNodeAttr << endl
00205 << " hasRegion : " << hasRegion << endl
00206 << endl;
00207
00208
00209
00210
00211
00212 pointField points(nNodes);
00213 Map<label> nodeToPoint(nNodes);
00214
00215 {
00216 labelList pointIndex(nNodes);
00217
00218 label pointI = 0;
00219
00220 while (nodeStream.good())
00221 {
00222 nodeStream.getLine(line);
00223
00224 if (line.size() && line[0] != '#')
00225 {
00226 IStringStream nodeLine(line);
00227
00228 label nodeI;
00229 scalar x, y, z;
00230 label dummy;
00231
00232 nodeLine >> nodeI >> x >> y >> z;
00233
00234 for (label i = 0; i < nNodeAttr; i++)
00235 {
00236 nodeLine >> dummy;
00237 }
00238
00239 if (hasRegion)
00240 {
00241 nodeLine >> dummy;
00242 }
00243
00244
00245 points[pointI] = point(x, y, z);
00246 nodeToPoint.insert(nodeI, pointI);
00247 pointI++;
00248 }
00249 }
00250 if (pointI != nNodes)
00251 {
00252 FatalIOErrorIn(args.executable().c_str(), nodeStream)
00253 << "Only " << pointI << " nodes present instead of " << nNodes
00254 << " from header." << exit(FatalIOError);
00255 }
00256 }
00257
00258
00259
00260
00261
00262 IFstream eleStream(eleFile);
00263
00264 do
00265 {
00266 eleStream.getLine(line);
00267 }
00268 while (line.size() && line[0] == '#');
00269
00270 IStringStream eleLine(line);
00271
00272 label nTets, nPtsPerTet, nElemAttr;
00273
00274 eleLine >> nTets >> nPtsPerTet >> nElemAttr;
00275
00276
00277 Info<< "Read .ele header:" << endl
00278 << " tets : " << nTets << endl
00279 << " pointsPerTet : " << nPtsPerTet << endl
00280 << " nAttr : " << nElemAttr << endl
00281 << endl;
00282
00283 if (nPtsPerTet != 4)
00284 {
00285 FatalIOErrorIn(args.executable().c_str(), eleStream)
00286 << "Cannot handle tets with "
00287 << nPtsPerTet << " points per tetrahedron in .ele file" << endl
00288 << "Can only handle tetrahedra with four points"
00289 << exit(FatalIOError);
00290 }
00291
00292 if (nElemAttr != 0)
00293 {
00294 WarningIn(args.executable())
00295 << "Element attributes (third elemenent in .ele header)"
00296 << " not used" << endl;
00297 }
00298
00299
00300
00301 const cellModel& tet = *(cellModeller::lookup("tet"));
00302
00303 labelList tetPoints(4);
00304
00305 cellShapeList cells(nTets);
00306 label cellI = 0;
00307
00308 while (eleStream.good())
00309 {
00310 eleStream.getLine(line);
00311
00312 if (line.size() && line[0] != '#')
00313 {
00314 IStringStream eleLine(line);
00315
00316 label elemI;
00317 eleLine >> elemI;
00318
00319 for (label i = 0; i < 4; i++)
00320 {
00321 label nodeI;
00322 eleLine >> nodeI;
00323 tetPoints[i] = nodeToPoint[nodeI];
00324 }
00325
00326 cells[cellI++] = cellShape(tet, tetPoints);
00327
00328
00329 for (label i = 0; i < nElemAttr; i++)
00330 {
00331 label dummy;
00332
00333 eleLine >> dummy;
00334 }
00335 }
00336 }
00337
00338
00339
00340
00341
00342
00343 autoPtr<polyMesh> meshPtr
00344 (
00345 new polyMesh
00346 (
00347 IOobject
00348 (
00349 polyMesh::defaultRegion,
00350 runTime.constant(),
00351 runTime
00352 ),
00353 xferCopy(points),
00354 cells,
00355 faceListList(0),
00356 wordList(0),
00357 wordList(0),
00358 "defaultFaces",
00359 polyPatch::typeName,
00360 wordList(0)
00361 )
00362 );
00363 const polyMesh& mesh = meshPtr;
00364
00365
00366
00367 if (readFaceFile)
00368 {
00369 label nPatches = 0;
00370
00371
00372 faceList boundaryFaces;
00373
00374
00375 labelList boundaryPatch;
00376
00377
00378
00379
00380
00381 IFstream faceStream(faceFile);
00382
00383 do
00384 {
00385 faceStream.getLine(line);
00386 }
00387 while (line.size() && line[0] == '#');
00388
00389 IStringStream faceLine(line);
00390
00391 label nFaces, nFaceAttr;
00392
00393 faceLine >> nFaces >> nFaceAttr;
00394
00395
00396 Info<< "Read .face header:" << endl
00397 << " faces : " << nFaces << endl
00398 << " nAttr : " << nFaceAttr << endl
00399 << endl;
00400
00401
00402 if (nFaceAttr != 1)
00403 {
00404 FatalIOErrorIn(args.executable().c_str(), faceStream)
00405 << "Expect boundary markers to be"
00406 << " present in .face file." << endl
00407 << "This is the second number in the header which is now:"
00408 << nFaceAttr << exit(FatalIOError);
00409 }
00410
00411
00412 boundaryFaces.setSize(nFaces);
00413
00414
00415 boundaryPatch.setSize(nFaces);
00416 boundaryPatch = -1;
00417
00418 label faceI = 0;
00419
00420
00421 Map<label> regionToPatch;
00422
00423 face f(3);
00424
00425 while (faceStream.good())
00426 {
00427 faceStream.getLine(line);
00428
00429 if (line.size() && line[0] != '#')
00430 {
00431 IStringStream faceLine(line);
00432
00433 label tetGenFaceI, dummy, region;
00434
00435 faceLine >> tetGenFaceI;
00436
00437
00438
00439 for (label i = 0; i < 3; i++)
00440 {
00441 label nodeI;
00442 faceLine >> nodeI;
00443 f[2-i] = nodeToPoint[nodeI];
00444 }
00445
00446
00447 if (findFace(mesh, f) >= mesh.nInternalFaces())
00448 {
00449 boundaryFaces[faceI] = f;
00450
00451 if (nFaceAttr > 0)
00452 {
00453
00454 faceLine >> region;
00455
00456
00457
00458 label patchI = 0;
00459
00460 Map<label>::iterator patchFind =
00461 regionToPatch.find(region);
00462
00463 if (patchFind == regionToPatch.end())
00464 {
00465 patchI = nPatches;
00466
00467 Info<< "Mapping tetgen region " << region
00468 << " to Foam patch "
00469 << patchI << endl;
00470
00471 regionToPatch.insert(region, nPatches++);
00472 }
00473 else
00474 {
00475 patchI = patchFind();
00476 }
00477
00478 boundaryPatch[faceI] = patchI;
00479
00480
00481 for (label i = 1; i < nFaceAttr; i++)
00482 {
00483 faceLine >> dummy;
00484 }
00485 }
00486
00487 faceI++;
00488 }
00489 }
00490 }
00491
00492
00493
00494 boundaryFaces.setSize(faceI);
00495 boundaryPatch.setSize(faceI);
00496
00497
00498
00499 Info<< "Regions:" << endl;
00500
00501 for
00502 (
00503 Map<label>::const_iterator iter = regionToPatch.begin();
00504 iter != regionToPatch.end();
00505 ++iter
00506 )
00507 {
00508 Info<< " region:" << iter.key() << '\t' << "patch:"
00509 << iter() << endl;
00510 }
00511 Info<< endl;
00512
00513
00514
00515 faceListList patchFaces(nPatches);
00516 wordList patchNames(nPatches);
00517
00518 forAll(patchNames, patchI)
00519 {
00520 patchNames[patchI] = word("patch") + name(patchI);
00521 }
00522
00523 wordList patchTypes(nPatches, polyPatch::typeName);
00524 word defaultFacesName = "defaultFaces";
00525 word defaultFacesType = polyPatch::typeName;
00526 wordList patchPhysicalTypes(nPatches, polyPatch::typeName);
00527
00528
00529
00530 List<DynamicList<face> > allPatchFaces(nPatches);
00531
00532 forAll(boundaryPatch, faceI)
00533 {
00534 label patchI = boundaryPatch[faceI];
00535
00536 allPatchFaces[patchI].append(boundaryFaces[faceI]);
00537 }
00538
00539 Info<< "Patch sizes:" << endl;
00540
00541 forAll(allPatchFaces, patchI)
00542 {
00543 Info<< " " << patchNames[patchI] << " : "
00544 << allPatchFaces[patchI].size() << endl;
00545
00546 patchFaces[patchI].transfer(allPatchFaces[patchI]);
00547 }
00548
00549 Info<< endl;
00550
00551
00552 meshPtr.reset
00553 (
00554 new polyMesh
00555 (
00556 IOobject
00557 (
00558 polyMesh::defaultRegion,
00559 runTime.constant(),
00560 runTime
00561 ),
00562 xferMove(points),
00563 cells,
00564 patchFaces,
00565 patchNames,
00566 patchTypes,
00567 defaultFacesName,
00568 defaultFacesType,
00569 patchPhysicalTypes
00570 )
00571 );
00572 }
00573
00574
00575 Info<< "Writing mesh to " << runTime.constant() << endl << endl;
00576
00577 meshPtr().write();
00578
00579 Info<< "End\n" << endl;
00580
00581 return 0;
00582 }
00583
00584
00585