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 #include "edgeCollapser.H"
00027 #include <OpenFOAM/polyMesh.H>
00028 #include "polyTopoChange.H"
00029 #include <OpenFOAM/ListOps.H>
00030
00031
00032
00033 Foam::label Foam::edgeCollapser::findIndex
00034 (
00035 const labelList& elems,
00036 const label start,
00037 const label size,
00038 const label val
00039 )
00040 {
00041 for (label i = start; i < size; i++)
00042 {
00043 if (elems[i] == val)
00044 {
00045 return i;
00046 }
00047 }
00048 return -1;
00049 }
00050
00051
00052
00053
00054
00055 Foam::label Foam::edgeCollapser::changePointRegion
00056 (
00057 const label pointI,
00058 const label oldRegion,
00059 const label newRegion
00060 )
00061 {
00062 label nChanged = 0;
00063
00064 if (pointRegion_[pointI] == oldRegion)
00065 {
00066 pointRegion_[pointI] = newRegion;
00067 nChanged++;
00068
00069
00070
00071 const labelList& pEdges = mesh_.pointEdges()[pointI];
00072
00073 forAll(pEdges, i)
00074 {
00075 label otherPointI = mesh_.edges()[pEdges[i]].otherVertex(pointI);
00076
00077 nChanged += changePointRegion(otherPointI, oldRegion, newRegion);
00078 }
00079 }
00080 return nChanged;
00081 }
00082
00083
00084 bool Foam::edgeCollapser::pointRemoved(const label pointI) const
00085 {
00086 label region = pointRegion_[pointI];
00087
00088 if (region == -1 || pointRegionMaster_[region] == pointI)
00089 {
00090 return false;
00091 }
00092 else
00093 {
00094 return true;
00095 }
00096 }
00097
00098
00099 void Foam::edgeCollapser::filterFace(const label faceI, face& f) const
00100 {
00101 label newFp = 0;
00102
00103 forAll(f, fp)
00104 {
00105 label pointI = f[fp];
00106
00107 label region = pointRegion_[pointI];
00108
00109 if (region == -1)
00110 {
00111 f[newFp++] = pointI;
00112 }
00113 else
00114 {
00115 label master = pointRegionMaster_[region];
00116
00117 if (findIndex(f, 0, newFp, master) == -1)
00118 {
00119 f[newFp++] = master;
00120 }
00121 }
00122 }
00123
00124
00125
00126
00127
00128
00129
00130 const label size = newFp;
00131
00132 newFp = 2;
00133
00134 for (label fp = 2; fp < size; fp++)
00135 {
00136 label fp1 = fp-1;
00137 label fp2 = fp-2;
00138
00139 label pointI = f[fp];
00140
00141
00142 label index = findIndex(f, 0, fp, pointI);
00143
00144 if (index == fp1)
00145 {
00146 WarningIn
00147 (
00148 "Foam::edgeCollapser::filterFace(const label faceI, "
00149 "face& f) const"
00150 ) << "Removing consecutive duplicate vertex in face "
00151 << f << endl;
00152
00153 }
00154 else if (index == fp2)
00155 {
00156 WarningIn
00157 (
00158 "Foam::edgeCollapser::filterFace(const label faceI, "
00159 "face& f) const"
00160 ) << "Removing non-consecutive duplicate vertex in face "
00161 << f << endl;
00162
00163 newFp--;
00164 }
00165 else if (index != -1)
00166 {
00167 WarningIn
00168 (
00169 "Foam::edgeCollapser::filterFace(const label faceI, "
00170 "face& f) const"
00171 ) << "Pinched face " << f << endl;
00172 f[newFp++] = pointI;
00173 }
00174 else
00175 {
00176 f[newFp++] = pointI;
00177 }
00178 }
00179
00180 f.setSize(newFp);
00181 }
00182
00183
00184
00185 void Foam::edgeCollapser::printRegions() const
00186 {
00187 forAll(pointRegionMaster_, regionI)
00188 {
00189 label master = pointRegionMaster_[regionI];
00190
00191 if (master != -1)
00192 {
00193 Info<< "Region:" << regionI << nl
00194 << " master:" << master
00195 << ' ' << mesh_.points()[master] << nl;
00196
00197 forAll(pointRegion_, pointI)
00198 {
00199 if (pointRegion_[pointI] == regionI && pointI != master)
00200 {
00201 Info<< " slave:" << pointI
00202 << ' ' << mesh_.points()[pointI] << nl;
00203 }
00204 }
00205 }
00206 }
00207 }
00208
00209
00210
00211
00212 void Foam::edgeCollapser::collapseEdges(const labelList& edgeLabels)
00213 {
00214 const edgeList& edges = mesh_.edges();
00215
00216 forAll(edgeLabels, i)
00217 {
00218 label edgeI = edgeLabels[i];
00219 const edge& e = edges[edgeI];
00220
00221 label region0 = pointRegion_[e[0]];
00222 label region1 = pointRegion_[e[1]];
00223
00224 if (region0 == -1)
00225 {
00226 if (region1 == -1)
00227 {
00228
00229 collapseEdge(edgeI, e[0]);
00230 }
00231 else
00232 {
00233
00234 collapseEdge(edgeI, e[1]);
00235 }
00236 }
00237 else
00238 {
00239 if (region1 == -1)
00240 {
00241
00242 collapseEdge(edgeI, e[0]);
00243 }
00244 else
00245 {
00246
00247 if (pointRegionMaster_[region0] == e[0])
00248 {
00249
00250 collapseEdge(edgeI, e[0]);
00251 }
00252 else if (pointRegionMaster_[region1] == e[1])
00253 {
00254
00255 collapseEdge(edgeI, e[1]);
00256 }
00257 else
00258 {
00259
00260 collapseEdge(edgeI, e[0]);
00261 }
00262 }
00263 }
00264 }
00265 }
00266
00267
00268
00269
00270
00271 Foam::edgeCollapser::edgeCollapser(const polyMesh& mesh)
00272 :
00273 mesh_(mesh),
00274 pointRegion_(mesh.nPoints(), -1),
00275 pointRegionMaster_(mesh.nPoints() / 100),
00276 freeRegions_()
00277 {}
00278
00279
00280
00281
00282 bool Foam::edgeCollapser::unaffectedEdge(const label edgeI) const
00283 {
00284 const edge& e = mesh_.edges()[edgeI];
00285
00286 return (pointRegion_[e[0]] == -1) && (pointRegion_[e[1]] == -1);
00287 }
00288
00289
00290 bool Foam::edgeCollapser::collapseEdge(const label edgeI, const label master)
00291 {
00292 const edge& e = mesh_.edges()[edgeI];
00293
00294 label pointRegion0 = pointRegion_[e[0]];
00295 label pointRegion1 = pointRegion_[e[1]];
00296
00297 if (pointRegion0 == -1)
00298 {
00299 if (pointRegion1 == -1)
00300 {
00301
00302
00303 label freeRegion = -1;
00304
00305 if (freeRegions_.size())
00306 {
00307 freeRegion = freeRegions_.removeHead();
00308
00309 if (pointRegionMaster_[freeRegion] != -1)
00310 {
00311 FatalErrorIn
00312 ("edgeCollapser::collapseEdge(const label, const label)")
00313 << "Problem : freeed region :" << freeRegion
00314 << " has already master "
00315 << pointRegionMaster_[freeRegion]
00316 << abort(FatalError);
00317 }
00318 }
00319 else
00320 {
00321
00322
00323 freeRegion = pointRegionMaster_.size();
00324 }
00325
00326 pointRegion_[e[0]] = freeRegion;
00327 pointRegion_[e[1]] = freeRegion;
00328
00329 pointRegionMaster_(freeRegion) = master;
00330 }
00331 else
00332 {
00333
00334 pointRegion_[e[0]] = pointRegion1;
00335
00336 pointRegionMaster_[pointRegion1] = master;
00337 }
00338 }
00339 else
00340 {
00341 if (pointRegion1 == -1)
00342 {
00343
00344 pointRegion_[e[1]] = pointRegion0;
00345
00346 pointRegionMaster_[pointRegion0] = master;
00347 }
00348 else if (pointRegion0 != pointRegion1)
00349 {
00350
00351
00352
00353 label minRegion = min(pointRegion0, pointRegion1);
00354 label maxRegion = max(pointRegion0, pointRegion1);
00355
00356
00357 pointRegionMaster_[minRegion] = master;
00358 pointRegionMaster_[maxRegion] = -1;
00359 freeRegions_.insert(maxRegion);
00360
00361 if (minRegion != pointRegion0)
00362 {
00363 changePointRegion(e[0], pointRegion0, minRegion);
00364 }
00365 if (minRegion != pointRegion1)
00366 {
00367 changePointRegion(e[1], pointRegion1, minRegion);
00368 }
00369 }
00370 }
00371
00372 return true;
00373 }
00374
00375
00376 bool Foam::edgeCollapser::setRefinement(polyTopoChange& meshMod)
00377 {
00378 const cellList& cells = mesh_.cells();
00379 const labelList& faceOwner = mesh_.faceOwner();
00380 const labelList& faceNeighbour = mesh_.faceNeighbour();
00381 const labelListList& pointFaces = mesh_.pointFaces();
00382 const labelListList& cellEdges = mesh_.cellEdges();
00383
00384
00385
00386
00387 bool meshChanged = false;
00388
00389
00390
00391 faceList newFaces(mesh_.faces());
00392
00393
00394 boolList cellRemoved(mesh_.nCells(), false);
00395
00396
00397 do
00398 {
00399
00400 forAll(newFaces, faceI)
00401 {
00402 filterFace(faceI, newFaces[faceI]);
00403 }
00404
00405
00406 label nCellCollapsed = 0;
00407
00408 forAll(cells, cellI)
00409 {
00410 if (!cellRemoved[cellI])
00411 {
00412 const cell& cFaces = cells[cellI];
00413
00414 label nFaces = cFaces.size();
00415
00416 forAll(cFaces, i)
00417 {
00418 label faceI = cFaces[i];
00419
00420 if (newFaces[faceI].size() < 3)
00421 {
00422 --nFaces;
00423
00424 if (nFaces < 4)
00425 {
00426 Info<< "Cell:" << cellI
00427 << " uses faces:" << cFaces
00428 << " of which too many are marked for removal:"
00429 << endl
00430 << " ";
00431 forAll(cFaces, j)
00432 {
00433 if (newFaces[cFaces[j]].size() < 3)
00434 {
00435 Info<< ' '<< cFaces[j];
00436 }
00437 }
00438 Info<< endl;
00439
00440 cellRemoved[cellI] = true;
00441
00442
00443 collapseEdges(cellEdges[cellI]);
00444
00445 nCellCollapsed++;
00446
00447 break;
00448 }
00449 }
00450 }
00451 }
00452 }
00453
00454 if (nCellCollapsed == 0)
00455 {
00456 break;
00457 }
00458 } while(true);
00459
00460
00461
00462 boolList doneFace(mesh_.nFaces(), false);
00463
00464 {
00465
00466 boolList usedPoint(mesh_.nPoints(), false);
00467
00468
00469 forAll(cellRemoved, cellI)
00470 {
00471 if (cellRemoved[cellI])
00472 {
00473 meshMod.removeCell(cellI, -1);
00474 }
00475 }
00476
00477
00478
00479 forAll(newFaces, faceI)
00480 {
00481 const face& f = newFaces[faceI];
00482
00483 if (f.size() < 3)
00484 {
00485 meshMod.removeFace(faceI, -1);
00486 meshChanged = true;
00487
00488
00489 doneFace[faceI] = true;
00490 }
00491 else
00492 {
00493
00494 forAll(f, fp)
00495 {
00496 usedPoint[f[fp]] = true;
00497 }
00498 }
00499 }
00500
00501
00502 forAll(usedPoint, pointI)
00503 {
00504 if (!usedPoint[pointI] && !pointRemoved(pointI))
00505 {
00506 meshMod.removePoint(pointI, -1);
00507 meshChanged = true;
00508 }
00509 }
00510 }
00511
00512
00513
00514
00515 forAll(pointRegion_, pointI)
00516 {
00517 if (pointRemoved(pointI))
00518 {
00519 meshMod.removePoint(pointI, -1);
00520 meshChanged = true;
00521 }
00522 }
00523
00524
00525
00526 const polyBoundaryMesh& boundaryMesh = mesh_.boundaryMesh();
00527 const faceZoneMesh& faceZones = mesh_.faceZones();
00528
00529
00530
00531 forAll(pointRegion_, pointI)
00532 {
00533 if (pointRemoved(pointI))
00534 {
00535 const labelList& changedFaces = pointFaces[pointI];
00536
00537 forAll(changedFaces, changedFaceI)
00538 {
00539 label faceI = changedFaces[changedFaceI];
00540
00541 if (!doneFace[faceI])
00542 {
00543 doneFace[faceI] = true;
00544
00545
00546 label zoneID = faceZones.whichZone(faceI);
00547
00548 bool zoneFlip = false;
00549
00550 if (zoneID >= 0)
00551 {
00552 const faceZone& fZone = faceZones[zoneID];
00553
00554 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
00555 }
00556
00557
00558 label own = faceOwner[faceI];
00559 label nei = -1;
00560 label patchID = -1;
00561
00562 if (mesh_.isInternalFace(faceI))
00563 {
00564 nei = faceNeighbour[faceI];
00565 }
00566 else
00567 {
00568 patchID = boundaryMesh.whichPatch(faceI);
00569 }
00570
00571 meshMod.modifyFace
00572 (
00573 newFaces[faceI],
00574 faceI,
00575 own,
00576 nei,
00577 false,
00578 patchID,
00579 zoneID,
00580 zoneFlip
00581 );
00582 meshChanged = true;
00583 }
00584 }
00585 }
00586 }
00587
00588 return meshChanged;
00589 }
00590
00591
00592 void Foam::edgeCollapser::updateMesh(const mapPolyMesh& map)
00593 {
00594 pointRegion_.setSize(mesh_.nPoints());
00595 pointRegion_ = -1;
00596
00597 pointRegionMaster_.clear();
00598 freeRegions_.clear();
00599 }
00600
00601
00602