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 "undoableMeshCutter.H"
00027 #include <OpenFOAM/polyMesh.H>
00028 #include <dynamicMesh/polyTopoChange.H>
00029 #include <OpenFOAM/DynamicList.H>
00030 #include <dynamicMesh/meshCutter.H>
00031 #include <dynamicMesh/cellCuts.H>
00032 #include <dynamicMesh/splitCell.H>
00033 #include <OpenFOAM/mapPolyMesh.H>
00034 #include <OpenFOAM/mathematicalConstants.H>
00035 #include <meshTools/meshTools.H>
00036
00037
00038
00039 namespace Foam
00040 {
00041
00042 defineTypeNameAndDebug(undoableMeshCutter, 0);
00043
00044 }
00045
00046
00047
00048
00049 void Foam::undoableMeshCutter::printCellRefTree
00050 (
00051 Ostream& os,
00052 const word& indent,
00053 const splitCell* splitCellPtr
00054 ) const
00055 {
00056 if (splitCellPtr)
00057 {
00058 os << indent << splitCellPtr->cellLabel() << endl;
00059
00060 word subIndent = indent + "--";
00061
00062 printCellRefTree(os, subIndent, splitCellPtr->master());
00063
00064 printCellRefTree(os, subIndent, splitCellPtr->slave());
00065 }
00066 }
00067
00068
00069
00070 void Foam::undoableMeshCutter::printRefTree(Ostream& os) const
00071 {
00072 for
00073 (
00074 Map<splitCell*>::const_iterator iter = liveSplitCells_.begin();
00075 iter != liveSplitCells_.end();
00076 ++iter
00077 )
00078 {
00079 const splitCell* splitPtr = iter();
00080
00081
00082 while (splitPtr->parent())
00083 {
00084 if (!splitPtr->isMaster())
00085 {
00086 splitPtr = NULL;
00087
00088 break;
00089 }
00090 else
00091 {
00092 splitPtr = splitPtr->parent();
00093 }
00094 }
00095
00096
00097 if (splitPtr)
00098 {
00099
00100 printCellRefTree(os, word(""), splitPtr);
00101 }
00102 }
00103 }
00104
00105
00106
00107
00108 void Foam::undoableMeshCutter::updateLabels
00109 (
00110 const labelList& map,
00111 Map<splitCell*>& liveSplitCells
00112 )
00113 {
00114
00115
00116 bool changed = false;
00117
00118 forAllConstIter(Map<splitCell*>,liveSplitCells, iter)
00119 {
00120 const splitCell* splitPtr = iter();
00121
00122 if (!splitPtr)
00123 {
00124 FatalErrorIn
00125 (
00126 "undoableMeshCutter::updateLabels"
00127 "(const labelList&, Map<splitCell*>&)"
00128 ) << "Problem: null pointer on liveSplitCells list"
00129 << abort(FatalError);
00130 }
00131
00132 label cellI = splitPtr->cellLabel();
00133
00134 if (cellI != map[cellI])
00135 {
00136 changed = true;
00137
00138 break;
00139 }
00140 }
00141
00142
00143
00144
00145 if (changed)
00146 {
00147
00148
00149 Map<splitCell*> newLiveSplitCells(2*liveSplitCells.size());
00150
00151 forAllIter(Map<splitCell*>, liveSplitCells, iter)
00152 {
00153 splitCell* splitPtr = iter();
00154
00155 label cellI = splitPtr->cellLabel();
00156
00157 label newCellI = map[cellI];
00158
00159 if (debug && (cellI != newCellI))
00160 {
00161 Pout<< "undoableMeshCutter::updateLabels :"
00162 << " Updating live (split)cell from " << cellI
00163 << " to " << newCellI << endl;
00164 }
00165
00166 if (newCellI >= 0)
00167 {
00168
00169
00170 splitPtr->cellLabel() = newCellI;
00171
00172
00173 newLiveSplitCells.insert(newCellI, splitPtr);
00174 }
00175 }
00176 liveSplitCells = newLiveSplitCells;
00177 }
00178 }
00179
00180
00181
00182
00183
00184 Foam::undoableMeshCutter::undoableMeshCutter
00185 (
00186 const polyMesh& mesh,
00187 const bool undoable
00188 )
00189 :
00190 meshCutter(mesh),
00191 undoable_(undoable),
00192 liveSplitCells_(mesh.nCells()/100 + 100),
00193 faceRemover_
00194 (
00195 mesh,
00196 Foam::cos(30./180. * mathematicalConstant::pi)
00197 )
00198 {}
00199
00200
00201
00202
00203 Foam::undoableMeshCutter::~undoableMeshCutter()
00204 {
00205
00206
00207 forAllIter(Map<splitCell*>, liveSplitCells_, iter)
00208 {
00209 splitCell* splitPtr = iter();
00210
00211 while (splitPtr)
00212 {
00213 splitCell* parentPtr = splitPtr->parent();
00214
00215
00216
00217 if (parentPtr)
00218 {
00219 splitCell* otherSidePtr = splitPtr->getOther();
00220
00221 otherSidePtr->parent() = NULL;
00222
00223 splitPtr->parent() = NULL;
00224 }
00225
00226
00227 delete splitPtr;
00228
00229 splitPtr = parentPtr;
00230 }
00231 }
00232 }
00233
00234
00235
00236
00237 void Foam::undoableMeshCutter::setRefinement
00238 (
00239 const cellCuts& cuts,
00240 polyTopoChange& meshMod
00241 )
00242 {
00243
00244 meshCutter::setRefinement(cuts, meshMod);
00245
00246 if (undoable_)
00247 {
00248
00249 forAllConstIter(Map<label>, addedCells(), iter)
00250 {
00251 label cellI = iter.key();
00252
00253 label addedCellI = iter();
00254
00255
00256
00257
00258
00259 Map<splitCell*>::iterator findCell =
00260 liveSplitCells_.find(cellI);
00261
00262 if (findCell == liveSplitCells_.end())
00263 {
00264
00265
00266
00267
00268
00269 splitCell* parentPtr = new splitCell(cellI, NULL);
00270
00271 splitCell* masterPtr = new splitCell(cellI, parentPtr);
00272
00273 splitCell* slavePtr = new splitCell(addedCellI, parentPtr);
00274
00275
00276
00277 parentPtr->master() = masterPtr;
00278 parentPtr->slave() = slavePtr;
00279
00280
00281
00282 if (liveSplitCells_.found(addedCellI))
00283 {
00284 FatalErrorIn("undoableMeshCutter::setRefinement")
00285 << "problem addedCell:" << addedCellI
00286 << abort(FatalError);
00287 }
00288
00289 liveSplitCells_.insert(cellI, masterPtr);
00290 liveSplitCells_.insert(addedCellI, slavePtr);
00291 }
00292 else
00293 {
00294
00295 splitCell* parentPtr = findCell();
00296
00297
00298 liveSplitCells_.erase(findCell);
00299
00300 splitCell* masterPtr = new splitCell(cellI, parentPtr);
00301
00302 splitCell* slavePtr = new splitCell(addedCellI, parentPtr);
00303
00304
00305
00306 parentPtr->master() = masterPtr;
00307 parentPtr->slave() = slavePtr;
00308
00309
00310
00311 if (liveSplitCells_.found(addedCellI))
00312 {
00313 FatalErrorIn("undoableMeshCutter::setRefinement")
00314 << "problem addedCell:" << addedCellI
00315 << abort(FatalError);
00316 }
00317
00318 liveSplitCells_.insert(cellI, masterPtr);
00319 liveSplitCells_.insert(addedCellI, slavePtr);
00320 }
00321 }
00322
00323 if (debug & 2)
00324 {
00325 Pout<< "** After refinement: liveSplitCells_:" << endl;
00326
00327 printRefTree(Pout);
00328 }
00329 }
00330 }
00331
00332
00333 void Foam::undoableMeshCutter::updateMesh(const mapPolyMesh& morphMap)
00334 {
00335
00336 meshCutter::updateMesh(morphMap);
00337
00338
00339
00340
00341 faceRemover_.updateMesh(morphMap);
00342
00343 if (undoable_)
00344 {
00345
00346 updateLabels(morphMap.reverseCellMap(), liveSplitCells_);
00347 }
00348 }
00349
00350
00351 Foam::labelList Foam::undoableMeshCutter::getSplitFaces() const
00352 {
00353 if (!undoable_)
00354 {
00355 FatalErrorIn("undoableMeshCutter::getSplitFaces()")
00356 << "Only call if constructed with unrefinement capability"
00357 << abort(FatalError);
00358 }
00359
00360 DynamicList<label> liveSplitFaces(liveSplitCells_.size());
00361
00362 forAllConstIter(Map<splitCell*>, liveSplitCells_, iter)
00363 {
00364 const splitCell* splitPtr = iter();
00365
00366 if (!splitPtr->parent())
00367 {
00368 FatalErrorIn("undoableMeshCutter::getSplitFaces()")
00369 << "Live split cell without parent" << endl
00370 << "splitCell:" << splitPtr->cellLabel()
00371 << abort(FatalError);
00372 }
00373
00374
00375 if (splitPtr->isMaster())
00376 {
00377 splitCell* slavePtr = splitPtr->getOther();
00378
00379 if
00380 (
00381 liveSplitCells_.found(slavePtr->cellLabel())
00382 && splitPtr->isUnrefined()
00383 && slavePtr->isUnrefined()
00384 )
00385 {
00386
00387
00388
00389 label cellI = splitPtr->cellLabel();
00390
00391 label slaveCellI = slavePtr->cellLabel();
00392
00393 label commonFaceI =
00394 meshTools::getSharedFace
00395 (
00396 mesh(),
00397 cellI,
00398 slaveCellI
00399 );
00400
00401 liveSplitFaces.append(commonFaceI);
00402 }
00403 }
00404 }
00405
00406 return liveSplitFaces.shrink();
00407 }
00408
00409
00410 Foam::Map<Foam::label> Foam::undoableMeshCutter::getAddedCells() const
00411 {
00412
00413
00414 if (!undoable_)
00415 {
00416 FatalErrorIn("undoableMeshCutter::getAddedCells()")
00417 << "Only call if constructed with unrefinement capability"
00418 << abort(FatalError);
00419 }
00420
00421 Map<label> addedCells(liveSplitCells_.size());
00422
00423 forAllConstIter(Map<splitCell*>, liveSplitCells_, iter)
00424 {
00425 const splitCell* splitPtr = iter();
00426
00427 if (!splitPtr->parent())
00428 {
00429 FatalErrorIn("undoableMeshCutter::getAddedCells()")
00430 << "Live split cell without parent" << endl
00431 << "splitCell:" << splitPtr->cellLabel()
00432 << abort(FatalError);
00433 }
00434
00435
00436 if (splitPtr->isMaster())
00437 {
00438 splitCell* slavePtr = splitPtr->getOther();
00439
00440 if
00441 (
00442 liveSplitCells_.found(slavePtr->cellLabel())
00443 && splitPtr->isUnrefined()
00444 && slavePtr->isUnrefined()
00445 )
00446 {
00447
00448 addedCells.insert(splitPtr->cellLabel(), slavePtr->cellLabel());
00449 }
00450 }
00451 }
00452 return addedCells;
00453 }
00454
00455
00456 Foam::labelList Foam::undoableMeshCutter::removeSplitFaces
00457 (
00458 const labelList& splitFaces,
00459 polyTopoChange& meshMod
00460 )
00461 {
00462 if (!undoable_)
00463 {
00464 FatalErrorIn("undoableMeshCutter::removeSplitFaces(const labelList&)")
00465 << "Only call if constructed with unrefinement capability"
00466 << abort(FatalError);
00467 }
00468
00469
00470
00471 labelList cellRegion;
00472 labelList cellRegionMaster;
00473 labelList facesToRemove;
00474
00475 faceRemover().compatibleRemoves
00476 (
00477 splitFaces,
00478 cellRegion,
00479 cellRegionMaster,
00480 facesToRemove
00481 );
00482
00483 if (facesToRemove.size() != splitFaces.size())
00484 {
00485 Pout<< "cellRegion:" << cellRegion << endl;
00486 Pout<< "cellRegionMaster:" << cellRegionMaster << endl;
00487
00488 FatalErrorIn
00489 (
00490 "undoableMeshCutter::removeSplitFaces(const labelList&)"
00491 ) << "Faces to remove:" << splitFaces << endl
00492 << "to be removed:" << facesToRemove
00493 << abort(FatalError);
00494 }
00495
00496
00497
00498
00499 forAll(facesToRemove, facesToRemoveI)
00500 {
00501 label faceI = facesToRemove[facesToRemoveI];
00502
00503 if (!mesh().isInternalFace(faceI))
00504 {
00505 FatalErrorIn
00506 (
00507 "undoableMeshCutter::removeSplitFaces(const labelList&)"
00508 ) << "Trying to remove face that is not internal"
00509 << abort(FatalError);
00510 }
00511
00512 label own = mesh().faceOwner()[faceI];
00513
00514 label nbr = mesh().faceNeighbour()[faceI];
00515
00516 Map<splitCell*>::iterator ownFind = liveSplitCells_.find(own);
00517
00518 Map<splitCell*>::iterator nbrFind = liveSplitCells_.find(nbr);
00519
00520 if
00521 (
00522 (ownFind == liveSplitCells_.end())
00523 || (nbrFind == liveSplitCells_.end())
00524 )
00525 {
00526
00527
00528 }
00529 else
00530 {
00531
00532
00533 splitCell* ownPtr = ownFind();
00534
00535 splitCell* nbrPtr = nbrFind();
00536
00537 splitCell* parentPtr = ownPtr->parent();
00538
00539
00540
00541 if (debug)
00542 {
00543 Pout<< "Updating for removed splitFace " << faceI
00544 << " own:" << own << " nbr:" << nbr
00545 << " ownPtr:" << ownPtr->cellLabel()
00546 << " nbrPtr:" << nbrPtr->cellLabel()
00547 << endl;
00548 }
00549 if (!parentPtr)
00550 {
00551 FatalErrorIn
00552 (
00553 "undoableMeshCutter::removeSplitFaces(const labelList&)"
00554 ) << "No parent for owner " << ownPtr->cellLabel()
00555 << abort(FatalError);
00556 }
00557
00558 if (!nbrPtr->parent())
00559 {
00560 FatalErrorIn
00561 (
00562 "undoableMeshCutter::removeSplitFaces(const labelList&)"
00563 ) << "No parent for neighbour " << nbrPtr->cellLabel()
00564 << abort(FatalError);
00565 }
00566
00567 if (parentPtr != nbrPtr->parent())
00568 {
00569 FatalErrorIn
00570 (
00571 "undoableMeshCutter::removeSplitFaces(const labelList&)"
00572 ) << "Owner and neighbour liveSplitCell entries do not have"
00573 << " same parent. faceI:" << faceI << " owner:" << own
00574 << " ownparent:" << parentPtr->cellLabel()
00575 << " neighbour:" << nbr
00576 << " nbrparent:" << nbrPtr->parent()->cellLabel()
00577 << abort(FatalError);
00578 }
00579
00580 if
00581 (
00582 !ownPtr->isUnrefined()
00583 || !nbrPtr->isUnrefined()
00584 || parentPtr->isUnrefined()
00585 )
00586 {
00587
00588 FatalErrorIn
00589 (
00590 "undoableMeshCutter::removeSplitFaces(const labelList&)"
00591 ) << "Owner and neighbour liveSplitCell entries are"
00592 << " refined themselves or the parent is not refined"
00593 << endl
00594 << "owner unrefined:" << ownPtr->isUnrefined()
00595 << " neighbour unrefined:" << nbrPtr->isUnrefined()
00596 << " master unrefined:" << parentPtr->isUnrefined()
00597 << abort(FatalError);
00598 }
00599
00600
00601 liveSplitCells_.erase(ownFind);
00602
00604 liveSplitCells_.erase(liveSplitCells_.find(nbr));
00605
00606
00607 delete ownPtr;
00608 delete nbrPtr;
00609
00610
00611
00612
00613
00614
00615
00616 if (parentPtr->parent())
00617 {
00618
00619
00620 parentPtr->cellLabel() = own;
00621
00622
00623
00624 liveSplitCells_.insert(own, parentPtr);
00625 }
00626 else
00627 {
00628
00629
00630 delete parentPtr;
00631 }
00632 }
00633 }
00634
00635
00636
00637 faceRemover().setRefinement
00638 (
00639 facesToRemove,
00640 cellRegion,
00641 cellRegionMaster,
00642 meshMod
00643 );
00644
00645 return facesToRemove;
00646 }
00647
00648
00649