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 #include <OpenFOAM/argList.H>
00071 #include <OpenFOAM/Time.H>
00072 #include <dynamicMesh/edgeCollapser.H>
00073 #include <dynamicMesh/polyTopoChange.H>
00074 #include <dynamicMesh/polyTopoChanger.H>
00075 #include <OpenFOAM/polyMesh.H>
00076 #include <OpenFOAM/mapPolyMesh.H>
00077 #include <OpenFOAM/mathematicalConstants.H>
00078 #include <OpenFOAM/PackedBoolList.H>
00079 #include <OpenFOAM/SortableList.H>
00080
00081 using namespace Foam;
00082
00083
00084
00085
00086
00087 labelList getSortedEdges
00088 (
00089 const edgeList& edges,
00090 const labelList& f,
00091 const labelList& edgeLabels
00092 )
00093 {
00094 labelList faceEdges(edgeLabels.size(), -1);
00095
00096
00097 forAll(edgeLabels, i)
00098 {
00099 label edgeI = edgeLabels[i];
00100
00101 const edge& e = edges[edgeI];
00102
00103 label fp = findIndex(f, e[0]);
00104 label fp1 = f.fcIndex(fp);
00105
00106 if (f[fp1] == e[1])
00107 {
00108
00109 faceEdges[fp] = edgeI;
00110 }
00111 else
00112 {
00113
00114 faceEdges[f.rcIndex(fp)] = edgeI;
00115 }
00116 }
00117
00118 return faceEdges;
00119 }
00120
00121
00122
00123 label mergeEdges
00124 (
00125 const polyMesh& mesh,
00126 const scalar maxCos,
00127 edgeCollapser& collapser
00128 )
00129 {
00130 const pointField& points = mesh.points();
00131 const edgeList& edges = mesh.edges();
00132 const labelListList& pointEdges = mesh.pointEdges();
00133 const labelList& region = collapser.pointRegion();
00134 const labelList& master = collapser.pointRegionMaster();
00135
00136 label nCollapsed = 0;
00137
00138 forAll(pointEdges, pointI)
00139 {
00140 const labelList& pEdges = pointEdges[pointI];
00141
00142 if (pEdges.size() == 2)
00143 {
00144 const edge& leftE = edges[pEdges[0]];
00145 const edge& rightE = edges[pEdges[1]];
00146
00147
00148 label leftV = leftE.otherVertex(pointI);
00149 label rightV = rightE.otherVertex(pointI);
00150
00151
00152
00153 label midMaster = -1;
00154 if (region[pointI] != -1)
00155 {
00156 midMaster = master[region[pointI]];
00157 }
00158
00159 label leftMaster = -2;
00160 if (region[leftV] != -1)
00161 {
00162 leftMaster = master[region[leftV]];
00163 }
00164
00165 label rightMaster = -3;
00166 if (region[rightV] != -1)
00167 {
00168 rightMaster = master[region[rightV]];
00169 }
00170
00171 if
00172 (
00173 midMaster != leftMaster
00174 && midMaster != rightMaster
00175 && leftMaster != rightMaster
00176 )
00177 {
00178
00179 vector leftVec = points[pointI] - points[leftV];
00180 leftVec /= mag(leftVec) + VSMALL;
00181
00182 vector rightVec = points[rightV] - points[pointI];
00183 rightVec /= mag(rightVec) + VSMALL;
00184
00185 if ((leftVec & rightVec) > maxCos)
00186 {
00187
00188
00189
00190 {
00191 collapser.collapseEdge(pEdges[0], leftV);
00192 nCollapsed++;
00193 }
00194 }
00195 }
00196 }
00197 }
00198
00199 return nCollapsed;
00200 }
00201
00202
00203
00204 label edgeMaster(const PackedBoolList& boundaryPoint, const edge& e)
00205 {
00206 label masterPoint = -1;
00207
00208
00209 if (boundaryPoint.get(e[0]))
00210 {
00211 if (boundaryPoint.get(e[1]))
00212 {
00213
00214
00215 masterPoint = e[0];
00216 }
00217 else
00218 {
00219 masterPoint = e[0];
00220 }
00221 }
00222 else
00223 {
00224 if (boundaryPoint.get(e[1]))
00225 {
00226 masterPoint = e[1];
00227 }
00228 else
00229 {
00230
00231
00232 masterPoint = e[0];
00233 }
00234 }
00235 return masterPoint;
00236 }
00237
00238
00239 label collapseSmallEdges
00240 (
00241 const polyMesh& mesh,
00242 const PackedBoolList& boundaryPoint,
00243 const scalar minLen,
00244 edgeCollapser& collapser
00245 )
00246 {
00247 const pointField& points = mesh.points();
00248 const edgeList& edges = mesh.edges();
00249
00250
00251
00252
00253 label nCollapsed = 0;
00254
00255 forAll(edges, edgeI)
00256 {
00257 const edge& e = edges[edgeI];
00258
00259 if (e.mag(points) < minLen)
00260 {
00261 label master = edgeMaster(boundaryPoint, e);
00262
00263 if (master != -1)
00264 {
00265 collapser.collapseEdge(edgeI, master);
00266 nCollapsed++;
00267 }
00268 }
00269 }
00270 return nCollapsed;
00271 }
00272
00273
00274
00275
00276
00277
00278 label collapseHighAspectFaces
00279 (
00280 const polyMesh& mesh,
00281 const PackedBoolList& boundaryPoint,
00282 const scalar areaFac,
00283 const scalar edgeRatio,
00284 edgeCollapser& collapser
00285 )
00286 {
00287 const pointField& points = mesh.points();
00288 const edgeList& edges = mesh.edges();
00289 const faceList& faces = mesh.faces();
00290 const labelListList& faceEdges = mesh.faceEdges();
00291
00292 scalarField magArea(mag(mesh.faceAreas()));
00293
00294 label maxIndex = findMax(magArea);
00295
00296 scalar minArea = areaFac * magArea[maxIndex];
00297
00298 Info<< "Max face area:" << magArea[maxIndex] << endl
00299 << "Collapse area factor:" << areaFac << endl
00300 << "Collapse area:" << minArea << endl;
00301
00302 label nCollapsed = 0;
00303
00304 forAll(faces, faceI)
00305 {
00306 if (magArea[faceI] < minArea)
00307 {
00308 const face& f = faces[faceI];
00309
00310
00311 labelList fEdges(getSortedEdges(edges, f, faceEdges[faceI]));
00312
00313 SortableList<scalar> lengths(fEdges.size());
00314 forAll(fEdges, i)
00315 {
00316 lengths[i] = edges[fEdges[i]].mag(points);
00317 }
00318 lengths.sort();
00319
00320
00321 label edgeI = -1;
00322
00323 if (f.size() == 4)
00324 {
00325
00326 if (lengths[2] > edgeRatio*lengths[0])
00327 {
00328
00329
00330 edgeI = fEdges[lengths.indices()[0]];
00331 }
00332 }
00333 else if (f.size() == 3)
00334 {
00335
00336 if (lengths[1] > edgeRatio*lengths[0])
00337 {
00338 edgeI = fEdges[lengths.indices()[0]];
00339 }
00340 }
00341
00342
00343 if (edgeI != -1)
00344 {
00345 label master = edgeMaster(boundaryPoint, edges[edgeI]);
00346
00347 if (master != -1)
00348 {
00349 collapser.collapseEdge(edgeI, master);
00350 nCollapsed++;
00351 }
00352 }
00353 }
00354 }
00355
00356 return nCollapsed;
00357 }
00358
00359
00360 void set(const labelList& elems, const bool val, boolList& status)
00361 {
00362 forAll(elems, i)
00363 {
00364 status[elems[i]] = val;
00365 }
00366 }
00367
00368
00369
00370 label simplifyFaces
00371 (
00372 const polyMesh& mesh,
00373 const PackedBoolList& boundaryPoint,
00374 const label minSize,
00375 const scalar lenGap,
00376 edgeCollapser& collapser
00377 )
00378 {
00379 const pointField& points = mesh.points();
00380 const edgeList& edges = mesh.edges();
00381 const faceList& faces = mesh.faces();
00382 const cellList& cells = mesh.cells();
00383 const labelListList& faceEdges = mesh.faceEdges();
00384 const labelList& faceOwner = mesh.faceOwner();
00385 const labelList& faceNeighbour = mesh.faceNeighbour();
00386 const labelListList& pointCells = mesh.pointCells();
00387 const labelListList& cellEdges = mesh.cellEdges();
00388
00389 label nCollapsed = 0;
00390
00391 boolList protectedEdge(mesh.nEdges(), false);
00392
00393 forAll(faces, faceI)
00394 {
00395 const face& f = faces[faceI];
00396
00397 if
00398 (
00399 f.size() > minSize
00400 && cells[faceOwner[faceI]].size() >= 6
00401 && (
00402 mesh.isInternalFace(faceI)
00403 && cells[faceNeighbour[faceI]].size() >= 6
00404 )
00405 )
00406 {
00407
00408 labelList fEdges(getSortedEdges(edges, f, faceEdges[faceI]));
00409
00410 SortableList<scalar> lengths(fEdges.size());
00411 forAll(fEdges, i)
00412 {
00413 lengths[i] = edges[fEdges[i]].mag(points);
00414 }
00415 lengths.sort();
00416
00417
00418
00419
00420
00421 label gapPos = -1;
00422
00423 for (label i = f.size()-1-minSize; i >= 0; --i)
00424 {
00425 if (lengths[i+1] > lenGap*lengths[i])
00426 {
00427 gapPos = i;
00428
00429 break;
00430 }
00431 }
00432
00433 if (gapPos != -1)
00434 {
00435
00436 label i = 0;
00437 {
00438 label edgeI = fEdges[lengths.indices()[i]];
00439
00440 if (!protectedEdge[edgeI])
00441 {
00442 const edge& e = edges[edgeI];
00443
00444 label master = edgeMaster(boundaryPoint, e);
00445
00446 if (master != -1)
00447 {
00448 collapser.collapseEdge(edgeI, master);
00449
00450
00451
00452
00453 const labelList& pCells0 = pointCells[e[0]];
00454
00455 forAll(pCells0, i)
00456 {
00457 set(cellEdges[pCells0[i]], true, protectedEdge);
00458 }
00459 const labelList& pCells1 = pointCells[e[1]];
00460
00461 forAll(pCells1, i)
00462 {
00463 set(cellEdges[pCells1[i]], true, protectedEdge);
00464 }
00465
00466 nCollapsed++;
00467 }
00468 }
00469 }
00470 }
00471 }
00472 }
00473
00474 return nCollapsed;
00475 }
00476
00477
00478
00479
00480 int main(int argc, char *argv[])
00481 {
00482 argList::noParallel();
00483 argList::validOptions.insert("overwrite", "");
00484 argList::validArgs.append("edge length [m]");
00485 argList::validArgs.append("merge angle (degrees)");
00486
00487 # include <OpenFOAM/setRootCase.H>
00488 # include <OpenFOAM/createTime.H>
00489 runTime.functionObjects().off();
00490 # include <OpenFOAM/createPolyMesh.H>
00491 const word oldInstance = mesh.pointsInstance();
00492
00493 scalar minLen(readScalar(IStringStream(args.additionalArgs()[0])()));
00494 scalar angle(readScalar(IStringStream(args.additionalArgs()[1])()));
00495 bool overwrite = args.optionFound("overwrite");
00496
00497 scalar maxCos = Foam::cos(angle*mathematicalConstant::pi/180.0);
00498
00499 Info<< "Merging:" << nl
00500 << " edges with length less than " << minLen << " meters" << nl
00501 << " edges split by a point with edges in line to within " << angle
00502 << " degrees" << nl
00503 << endl;
00504
00505
00506 bool meshChanged = false;
00507
00508 while (true)
00509 {
00510 const faceList& faces = mesh.faces();
00511
00512
00513 PackedBoolList boundaryPoint(mesh.nPoints());
00514
00515 label nIntFaces = mesh.nInternalFaces();
00516 for (label faceI = nIntFaces; faceI < mesh.nFaces(); faceI++)
00517 {
00518 const face& f = faces[faceI];
00519
00520 forAll(f, fp)
00521 {
00522 boundaryPoint.set(f[fp], 1);
00523 }
00524 }
00525
00526
00527 edgeCollapser collapser(mesh);
00528
00529
00530
00531 label nCollapsed =
00532 collapseSmallEdges
00533 (
00534 mesh,
00535 boundaryPoint,
00536 minLen,
00537 collapser
00538 );
00539 Info<< "Collapsing " << nCollapsed << " small edges" << endl;
00540
00541
00542
00543 if (nCollapsed == 0)
00544 {
00545 nCollapsed = mergeEdges(mesh, maxCos, collapser);
00546 Info<< "Collapsing " << nCollapsed << " in line edges" << endl;
00547 }
00548
00549
00550
00551 if (nCollapsed == 0)
00552 {
00553 nCollapsed =
00554 collapseHighAspectFaces
00555 (
00556 mesh,
00557 boundaryPoint,
00558 1E-9,
00559 5,
00560
00561 collapser
00562 );
00563 Info<< "Collapsing " << nCollapsed
00564 << " small high aspect ratio faces" << endl;
00565 }
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 if (nCollapsed == 0)
00584 {
00585 break;
00586 }
00587
00588 polyTopoChange meshMod(mesh);
00589
00590
00591 collapser.setRefinement(meshMod);
00592
00593
00594 Info<< "Morphing ..." << endl;
00595
00596 autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(mesh, false);
00597
00598 collapser.updateMesh(morphMap());
00599
00600 if (morphMap().hasMotionPoints())
00601 {
00602 mesh.movePoints(morphMap().preMotionPoints());
00603 }
00604
00605 meshChanged = true;
00606 }
00607
00608 if (meshChanged)
00609 {
00610
00611 if (!overwrite)
00612 {
00613 runTime++;
00614 }
00615 else
00616 {
00617 mesh.setInstance(oldInstance);
00618 }
00619
00620 Info<< "Writing collapsed mesh to time " << runTime.timeName() << endl;
00621
00622 mesh.write();
00623 }
00624
00625 Info << "End\n" << endl;
00626
00627 return 0;
00628 }
00629
00630
00631