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 #include "autoLayerDriver.H"
00030 #include <finiteVolume/fvMesh.H>
00031 #include <OpenFOAM/Time.H>
00032 #include <autoMesh/meshRefinement.H>
00033 #include <dynamicMesh/removePoints.H>
00034 #include <OpenFOAM/pointFields.H>
00035 #include <dynamicMesh/motionSmoother.H>
00036 #include <OpenFOAM/mathematicalConstants.H>
00037 #include <meshTools/pointSet.H>
00038 #include <meshTools/faceSet.H>
00039 #include <meshTools/cellSet.H>
00040 #include <dynamicMesh/polyTopoChange.H>
00041 #include <OpenFOAM/mapPolyMesh.H>
00042 #include <dynamicMesh/addPatchCellLayer.H>
00043 #include <OpenFOAM/mapDistributePolyMesh.H>
00044 #include <OpenFOAM/OFstream.H>
00045 #include <autoMesh/layerParameters.H>
00046 #include <dynamicMesh/combineFaces.H>
00047 #include <OpenFOAM/IOmanip.H>
00048
00049
00050
00051 namespace Foam
00052 {
00053
00054 defineTypeNameAndDebug(autoLayerDriver, 0);
00055
00056 }
00057
00058
00059
00060
00061 Foam::label Foam::autoLayerDriver::mergePatchFacesUndo
00062 (
00063 const scalar minCos,
00064 const scalar concaveCos,
00065 const dictionary& motionDict
00066 )
00067 {
00068 fvMesh& mesh = meshRefiner_.mesh();
00069
00070
00071 combineFaces faceCombiner(mesh, true);
00072
00073
00074 labelHashSet boundaryCells(mesh.nFaces()-mesh.nInternalFaces());
00075
00076 {
00077 labelList patchIDs(meshRefiner_.meshedPatches());
00078
00079 const polyBoundaryMesh& patches = mesh.boundaryMesh();
00080
00081 forAll(patchIDs, i)
00082 {
00083 label patchI = patchIDs[i];
00084
00085 const polyPatch& patch = patches[patchI];
00086
00087 if (!patch.coupled())
00088 {
00089 forAll(patch, i)
00090 {
00091 boundaryCells.insert(mesh.faceOwner()[patch.start()+i]);
00092 }
00093 }
00094 }
00095 }
00096
00097
00098 labelListList allFaceSets
00099 (
00100 faceCombiner.getMergeSets
00101 (
00102 minCos,
00103 concaveCos,
00104 boundaryCells
00105 )
00106 );
00107
00108 label nFaceSets = returnReduce(allFaceSets.size(), sumOp<label>());
00109
00110 Info<< "Merging " << nFaceSets << " sets of faces." << nl << endl;
00111
00112 if (nFaceSets > 0)
00113 {
00114 if (debug)
00115 {
00116 faceSet allSets(mesh, "allFaceSets", allFaceSets.size());
00117 forAll(allFaceSets, setI)
00118 {
00119 forAll(allFaceSets[setI], i)
00120 {
00121 allSets.insert(allFaceSets[setI][i]);
00122 }
00123 }
00124 Pout<< "Writing all faces to be merged to set "
00125 << allSets.objectPath() << endl;
00126 allSets.write();
00127 }
00128
00129
00130
00131 polyTopoChange meshMod(mesh);
00132
00133
00134 faceCombiner.setRefinement(allFaceSets, meshMod);
00135
00136
00137 meshRefiner_.storeData
00138 (
00139 faceCombiner.savedPointLabels(),
00140 labelList(0),
00141 labelList(0)
00142 );
00143
00144
00145 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false, true);
00146
00147
00148 mesh.updateMesh(map);
00149
00150
00151 if (map().hasMotionPoints())
00152 {
00153 mesh.movePoints(map().preMotionPoints());
00154 }
00155 else
00156 {
00157
00158 mesh.clearOut();
00159 }
00160
00161 if (meshRefiner_.overwrite())
00162 {
00163 mesh.setInstance(meshRefiner_.oldInstance());
00164 }
00165
00166 faceCombiner.updateMesh(map);
00167
00168 meshRefiner_.updateMesh(map, labelList(0));
00169
00170
00171 for (label iteration = 0; iteration < 100; iteration++)
00172 {
00173 Info<< nl
00174 << "Undo iteration " << iteration << nl
00175 << "----------------" << endl;
00176
00177
00178
00179
00180
00181 faceSet errorFaces
00182 (
00183 mesh,
00184 "errorFaces",
00185 mesh.nFaces()-mesh.nInternalFaces()
00186 );
00187 bool hasErrors = motionSmoother::checkMesh
00188 (
00189 false,
00190 mesh,
00191 motionDict,
00192 errorFaces
00193 );
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 if (!hasErrors)
00216 {
00217 break;
00218 }
00219
00220
00221 if (debug)
00222 {
00223 Pout<< "Writing all faces in error to faceSet "
00224 << errorFaces.objectPath() << nl << endl;
00225 errorFaces.write();
00226 }
00227
00228
00229
00230
00231
00232 DynamicList<label> mastersToRestore(allFaceSets.size());
00233
00234 forAll(allFaceSets, setI)
00235 {
00236 label masterFaceI = faceCombiner.masterFace()[setI];
00237
00238 if (masterFaceI != -1)
00239 {
00240 label masterCellII = mesh.faceOwner()[masterFaceI];
00241
00242 const cell& cFaces = mesh.cells()[masterCellII];
00243
00244 forAll(cFaces, i)
00245 {
00246 if (errorFaces.found(cFaces[i]))
00247 {
00248 mastersToRestore.append(masterFaceI);
00249 break;
00250 }
00251 }
00252 }
00253 }
00254 mastersToRestore.shrink();
00255
00256 label nRestore = returnReduce
00257 (
00258 mastersToRestore.size(),
00259 sumOp<label>()
00260 );
00261
00262 Info<< "Masters that need to be restored:"
00263 << nRestore << endl;
00264
00265 if (debug)
00266 {
00267 faceSet restoreSet(mesh, "mastersToRestore", mastersToRestore);
00268 Pout<< "Writing all " << mastersToRestore.size()
00269 << " masterfaces to be restored to set "
00270 << restoreSet.objectPath() << endl;
00271 restoreSet.write();
00272 }
00273
00274
00275 if (nRestore == 0)
00276 {
00277 break;
00278 }
00279
00280
00281
00282
00283
00284
00285 polyTopoChange meshMod(mesh);
00286
00287
00288
00289 Map<label> restoredPoints(0);
00290 Map<label> restoredFaces(0);
00291 Map<label> restoredCells(0);
00292
00293 faceCombiner.setUnrefinement
00294 (
00295 mastersToRestore,
00296 meshMod,
00297 restoredPoints,
00298 restoredFaces,
00299 restoredCells
00300 );
00301
00302
00303 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false, true);
00304
00305
00306 mesh.updateMesh(map);
00307
00308
00309 if (map().hasMotionPoints())
00310 {
00311 mesh.movePoints(map().preMotionPoints());
00312 }
00313 else
00314 {
00315
00316 mesh.clearOut();
00317 }
00318
00319 if (meshRefiner_.overwrite())
00320 {
00321 mesh.setInstance(meshRefiner_.oldInstance());
00322 }
00323
00324 faceCombiner.updateMesh(map);
00325
00326
00327 inplaceMapKey(map().reversePointMap(), restoredPoints);
00328 inplaceMapKey(map().reverseFaceMap(), restoredFaces);
00329 inplaceMapKey(map().reverseCellMap(), restoredCells);
00330
00331
00332 meshRefiner_.updateMesh
00333 (
00334 map,
00335 labelList(0),
00336 restoredPoints,
00337 restoredFaces,
00338 restoredCells
00339 );
00340
00341 Info<< endl;
00342 }
00343
00344 if (debug)
00345 {
00346 Pout<< "Writing merged-faces mesh to time "
00347 << meshRefiner_.timeName() << nl << endl;
00348 mesh.write();
00349 }
00350 }
00351 else
00352 {
00353 Info<< "No faces merged ..." << endl;
00354 }
00355
00356 return nFaceSets;
00357 }
00358
00359
00360
00361 Foam::autoPtr<Foam::mapPolyMesh> Foam::autoLayerDriver::doRemovePoints
00362 (
00363 removePoints& pointRemover,
00364 const boolList& pointCanBeDeleted
00365 )
00366 {
00367 fvMesh& mesh = meshRefiner_.mesh();
00368
00369
00370 polyTopoChange meshMod(mesh);
00371
00372 pointRemover.setRefinement(pointCanBeDeleted, meshMod);
00373
00374
00375 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false, true);
00376
00377
00378 mesh.updateMesh(map);
00379
00380
00381 if (map().hasMotionPoints())
00382 {
00383 mesh.movePoints(map().preMotionPoints());
00384 }
00385 else
00386 {
00387
00388 mesh.clearOut();
00389 }
00390
00391 if (meshRefiner_.overwrite())
00392 {
00393 mesh.setInstance(meshRefiner_.oldInstance());
00394 }
00395
00396 pointRemover.updateMesh(map);
00397 meshRefiner_.updateMesh(map, labelList(0));
00398
00399 return map;
00400 }
00401
00402
00403
00404 Foam::autoPtr<Foam::mapPolyMesh> Foam::autoLayerDriver::doRestorePoints
00405 (
00406 removePoints& pointRemover,
00407 const labelList& facesToRestore
00408 )
00409 {
00410 fvMesh& mesh = meshRefiner_.mesh();
00411
00412
00413 polyTopoChange meshMod(mesh);
00414
00415
00416 labelList localFaces, localPoints;
00417 pointRemover.getUnrefimentSet
00418 (
00419 facesToRestore,
00420 localFaces,
00421 localPoints
00422 );
00423
00424
00425 pointRemover.setUnrefinement
00426 (
00427 localFaces,
00428 localPoints,
00429 meshMod
00430 );
00431
00432
00433 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false, true);
00434
00435
00436 mesh.updateMesh(map);
00437
00438
00439 if (map().hasMotionPoints())
00440 {
00441 mesh.movePoints(map().preMotionPoints());
00442 }
00443 else
00444 {
00445
00446 mesh.clearOut();
00447 }
00448
00449 if (meshRefiner_.overwrite())
00450 {
00451 mesh.setInstance(meshRefiner_.oldInstance());
00452 }
00453
00454 pointRemover.updateMesh(map);
00455 meshRefiner_.updateMesh(map, labelList(0));
00456
00457 return map;
00458 }
00459
00460
00461
00462
00463 Foam::labelList Foam::autoLayerDriver::collectFaces
00464 (
00465 const labelList& candidateFaces,
00466 const labelHashSet& set
00467 ) const
00468 {
00469 const fvMesh& mesh = meshRefiner_.mesh();
00470
00471
00472 boolList selected(mesh.nFaces(), false);
00473
00474 forAll(candidateFaces, i)
00475 {
00476 label faceI = candidateFaces[i];
00477
00478 if (set.found(faceI))
00479 {
00480 selected[faceI] = true;
00481 }
00482 }
00483 syncTools::syncFaceList
00484 (
00485 mesh,
00486 selected,
00487 orEqOp<bool>(),
00488 false
00489 );
00490
00491 labelList selectedFaces(findIndices(selected, true));
00492
00493 return selectedFaces;
00494 }
00495
00496
00497
00498 Foam::labelList Foam::autoLayerDriver::growFaceCellFace
00499 (
00500 const labelHashSet& set
00501 ) const
00502 {
00503 const fvMesh& mesh = meshRefiner_.mesh();
00504
00505 boolList selected(mesh.nFaces(), false);
00506
00507 forAllConstIter(faceSet, set, iter)
00508 {
00509 label faceI = iter.key();
00510
00511 label own = mesh.faceOwner()[faceI];
00512
00513 const cell& ownFaces = mesh.cells()[own];
00514 forAll(ownFaces, ownFaceI)
00515 {
00516 selected[ownFaces[ownFaceI]] = true;
00517 }
00518
00519 if (mesh.isInternalFace(faceI))
00520 {
00521 label nbr = mesh.faceNeighbour()[faceI];
00522
00523 const cell& nbrFaces = mesh.cells()[nbr];
00524 forAll(nbrFaces, nbrFaceI)
00525 {
00526 selected[nbrFaces[nbrFaceI]] = true;
00527 }
00528 }
00529 }
00530 syncTools::syncFaceList
00531 (
00532 mesh,
00533 selected,
00534 orEqOp<bool>(),
00535 false
00536 );
00537 return findIndices(selected, true);
00538 }
00539
00540
00541
00542
00543 Foam::label Foam::autoLayerDriver::mergeEdgesUndo
00544 (
00545 const scalar minCos,
00546 const dictionary& motionDict
00547 )
00548 {
00549 fvMesh& mesh = meshRefiner_.mesh();
00550
00551 Info<< nl
00552 << "Merging all points on surface that" << nl
00553 << "- are used by only two boundary faces and" << nl
00554 << "- make an angle with a cosine of more than " << minCos
00555 << "." << nl << endl;
00556
00557
00558 removePoints pointRemover(mesh, true);
00559
00560
00561 boolList pointCanBeDeleted;
00562 label nRemove = pointRemover.countPointUsage(minCos, pointCanBeDeleted);
00563
00564 if (nRemove > 0)
00565 {
00566 Info<< "Removing " << nRemove
00567 << " straight edge points ..." << nl << endl;
00568
00569
00570
00571
00572 doRemovePoints(pointRemover, pointCanBeDeleted);
00573
00574
00575 for (label iteration = 0; iteration < 100; iteration++)
00576 {
00577 Info<< nl
00578 << "Undo iteration " << iteration << nl
00579 << "----------------" << endl;
00580
00581
00582
00583
00584
00585 faceSet errorFaces
00586 (
00587 mesh,
00588 "errorFaces",
00589 mesh.nFaces()-mesh.nInternalFaces()
00590 );
00591 bool hasErrors = motionSmoother::checkMesh
00592 (
00593 false,
00594 mesh,
00595 motionDict,
00596 errorFaces
00597 );
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619 if (!hasErrors)
00620 {
00621 break;
00622 }
00623
00624 if (debug)
00625 {
00626 Pout<< "**Writing all faces in error to faceSet "
00627 << errorFaces.objectPath() << nl << endl;
00628 errorFaces.write();
00629 }
00630
00631 labelList masterErrorFaces
00632 (
00633 collectFaces
00634 (
00635 pointRemover.savedFaceLabels(),
00636 errorFaces
00637 )
00638 );
00639
00640 label n = returnReduce(masterErrorFaces.size(), sumOp<label>());
00641
00642 Info<< "Detected " << n
00643 << " error faces on boundaries that have been merged."
00644 << " These will be restored to their original faces." << nl
00645 << endl;
00646
00647 if (n == 0)
00648 {
00649 if (hasErrors)
00650 {
00651 Info<< "Detected "
00652 << returnReduce(errorFaces.size(), sumOp<label>())
00653 << " error faces in mesh."
00654 << " Restoring neighbours of faces in error." << nl
00655 << endl;
00656
00657 labelList expandedErrorFaces
00658 (
00659 growFaceCellFace
00660 (
00661 errorFaces
00662 )
00663 );
00664
00665 doRestorePoints(pointRemover, expandedErrorFaces);
00666 }
00667
00668 break;
00669 }
00670
00671 doRestorePoints(pointRemover, masterErrorFaces);
00672 }
00673
00674 if (debug)
00675 {
00676 Pout<< "Writing merged-edges mesh to time "
00677 << meshRefiner_.timeName() << nl << endl;
00678 mesh.write();
00679 }
00680 }
00681 else
00682 {
00683 Info<< "No straight edges simplified and no points removed ..." << endl;
00684 }
00685
00686 return nRemove;
00687 }
00688
00689
00690
00691 void Foam::autoLayerDriver::dumpDisplacement
00692 (
00693 const fileName& prefix,
00694 const indirectPrimitivePatch& pp,
00695 const vectorField& patchDisp,
00696 const List<extrudeMode>& extrudeStatus
00697 )
00698 {
00699 OFstream dispStr(prefix + "_disp.obj");
00700 Info<< "Writing all displacements to " << dispStr.name() << nl << endl;
00701
00702 label vertI = 0;
00703
00704 forAll(patchDisp, patchPointI)
00705 {
00706 const point& pt = pp.localPoints()[patchPointI];
00707
00708 meshTools::writeOBJ(dispStr, pt); vertI++;
00709 meshTools::writeOBJ(dispStr, pt + patchDisp[patchPointI]); vertI++;
00710
00711 dispStr << "l " << vertI-1 << ' ' << vertI << nl;
00712 }
00713
00714
00715 OFstream illStr(prefix + "_illegal.obj");
00716 Info<< "Writing invalid displacements to " << illStr.name() << nl << endl;
00717
00718 vertI = 0;
00719
00720 forAll(patchDisp, patchPointI)
00721 {
00722 if (extrudeStatus[patchPointI] != EXTRUDE)
00723 {
00724 const point& pt = pp.localPoints()[patchPointI];
00725
00726 meshTools::writeOBJ(illStr, pt); vertI++;
00727 meshTools::writeOBJ(illStr, pt + patchDisp[patchPointI]); vertI++;
00728
00729 illStr << "l " << vertI-1 << ' ' << vertI << nl;
00730 }
00731 }
00732 }
00733
00734
00735
00736
00737 void Foam::autoLayerDriver::checkManifold
00738 (
00739 const indirectPrimitivePatch& fp,
00740 pointSet& nonManifoldPoints
00741 )
00742 {
00743
00744 fp.checkPointManifold(false, &nonManifoldPoints);
00745
00746
00747 const labelListList& edgeFaces = fp.edgeFaces();
00748
00749 forAll(edgeFaces, edgeI)
00750 {
00751 const labelList& eFaces = edgeFaces[edgeI];
00752
00753 if (eFaces.size() > 2)
00754 {
00755 const edge& e = fp.edges()[edgeI];
00756
00757 nonManifoldPoints.insert(fp.meshPoints()[e[0]]);
00758 nonManifoldPoints.insert(fp.meshPoints()[e[1]]);
00759 }
00760 }
00761 }
00762
00763
00764 void Foam::autoLayerDriver::checkMeshManifold() const
00765 {
00766 const fvMesh& mesh = meshRefiner_.mesh();
00767
00768 Info<< nl << "Checking mesh manifoldness ..." << endl;
00769
00770
00771 labelList outsideFaces(mesh.nFaces() - mesh.nInternalFaces());
00772
00773 for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++)
00774 {
00775 outsideFaces[faceI - mesh.nInternalFaces()] = faceI;
00776 }
00777
00778 pointSet nonManifoldPoints
00779 (
00780 mesh,
00781 "nonManifoldPoints",
00782 mesh.nPoints() / 100
00783 );
00784
00785
00786 checkManifold
00787 (
00788 indirectPrimitivePatch
00789 (
00790 IndirectList<face>(mesh.faces(), outsideFaces),
00791 mesh.points()
00792 ),
00793 nonManifoldPoints
00794 );
00795
00796 label nNonManif = returnReduce(nonManifoldPoints.size(), sumOp<label>());
00797
00798 if (nNonManif > 0)
00799 {
00800 Info<< "Outside of mesh is multiply connected across edges or"
00801 << " points." << nl
00802 << "This is not a fatal error but might cause some unexpected"
00803 << " behaviour." << nl
00804 << "Writing " << nNonManif
00805 << " points where this happens to pointSet "
00806 << nonManifoldPoints.name() << endl;
00807
00808 nonManifoldPoints.write();
00809 }
00810 Info<< endl;
00811 }
00812
00813
00814
00815
00816 bool Foam::autoLayerDriver::unmarkExtrusion
00817 (
00818 const label patchPointI,
00819 pointField& patchDisp,
00820 labelList& patchNLayers,
00821 List<extrudeMode>& extrudeStatus
00822 )
00823 {
00824 if (extrudeStatus[patchPointI] == EXTRUDE)
00825 {
00826 extrudeStatus[patchPointI] = NOEXTRUDE;
00827 patchNLayers[patchPointI] = 0;
00828 patchDisp[patchPointI] = vector::zero;
00829 return true;
00830 }
00831 else if (extrudeStatus[patchPointI] == EXTRUDEREMOVE)
00832 {
00833 extrudeStatus[patchPointI] = NOEXTRUDE;
00834 patchNLayers[patchPointI] = 0;
00835 patchDisp[patchPointI] = vector::zero;
00836 return true;
00837 }
00838 else
00839 {
00840 return false;
00841 }
00842 }
00843
00844
00845
00846 bool Foam::autoLayerDriver::unmarkExtrusion
00847 (
00848 const face& localFace,
00849 pointField& patchDisp,
00850 labelList& patchNLayers,
00851 List<extrudeMode>& extrudeStatus
00852 )
00853 {
00854 bool unextruded = false;
00855
00856 forAll(localFace, fp)
00857 {
00858 if
00859 (
00860 unmarkExtrusion
00861 (
00862 localFace[fp],
00863 patchDisp,
00864 patchNLayers,
00865 extrudeStatus
00866 )
00867 )
00868 {
00869 unextruded = true;
00870 }
00871 }
00872 return unextruded;
00873 }
00874
00875
00876
00877 void Foam::autoLayerDriver::handleNonManifolds
00878 (
00879 const indirectPrimitivePatch& pp,
00880 const labelList& meshEdges,
00881 pointField& patchDisp,
00882 labelList& patchNLayers,
00883 List<extrudeMode>& extrudeStatus
00884 ) const
00885 {
00886 const fvMesh& mesh = meshRefiner_.mesh();
00887
00888 Info<< nl << "Handling non-manifold points ..." << endl;
00889
00890
00891 Info<< nl << "Checking patch manifoldness ..." << endl;
00892
00893 pointSet nonManifoldPoints(mesh, "nonManifoldPoints", pp.nPoints());
00894
00895
00896 checkManifold(pp, nonManifoldPoints);
00897
00898 label nNonManif = returnReduce(nonManifoldPoints.size(), sumOp<label>());
00899
00900 Info<< "Outside of local patch is multiply connected across edges or"
00901 << " points at " << nNonManif << " points." << endl;
00902
00903
00904 const labelList& meshPoints = pp.meshPoints();
00905
00906
00907
00908
00909 const labelHashSet sharedEdgeSet(mesh.globalData().sharedEdgeLabels());
00910
00911 forAll(pp.edges(), edgeI)
00912 {
00913 if (sharedEdgeSet.found(meshEdges[edgeI]))
00914 {
00915 const edge& e = mesh.edges()[meshEdges[edgeI]];
00916
00917 Pout<< "Disabling extrusion at edge "
00918 << mesh.points()[e[0]] << mesh.points()[e[1]]
00919 << " since it is non-manifold across coupled patches."
00920 << endl;
00921
00922 nonManifoldPoints.insert(e[0]);
00923 nonManifoldPoints.insert(e[1]);
00924 }
00925 }
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935 nNonManif = returnReduce(nonManifoldPoints.size(), sumOp<label>());
00936
00937 if (nNonManif > 0)
00938 {
00939 Info<< "Outside of patches is multiply connected across edges or"
00940 << " points at " << nNonManif << " points." << nl
00941 << "Writing " << nNonManif
00942 << " points where this happens to pointSet "
00943 << nonManifoldPoints.name() << nl
00944 << "and setting layer thickness to zero on these points."
00945 << endl;
00946
00947 nonManifoldPoints.write();
00948
00949 forAll(meshPoints, patchPointI)
00950 {
00951 if (nonManifoldPoints.found(meshPoints[patchPointI]))
00952 {
00953 unmarkExtrusion
00954 (
00955 patchPointI,
00956 patchDisp,
00957 patchNLayers,
00958 extrudeStatus
00959 );
00960 }
00961 }
00962 }
00963
00964 Info<< "Set displacement to zero for all " << nNonManif
00965 << " non-manifold points" << endl;
00966 }
00967
00968
00969
00970 void Foam::autoLayerDriver::handleFeatureAngle
00971 (
00972 const indirectPrimitivePatch& pp,
00973 const labelList& meshEdges,
00974 const scalar minCos,
00975 pointField& patchDisp,
00976 labelList& patchNLayers,
00977 List<extrudeMode>& extrudeStatus
00978 ) const
00979 {
00980 const fvMesh& mesh = meshRefiner_.mesh();
00981
00982 Info<< nl << "Handling feature edges ..." << endl;
00983
00984 if (minCos < 1-SMALL)
00985 {
00986
00987 vectorField edgeNormal(mesh.nEdges(), wallPoint::greatPoint);
00988
00989 const labelListList& edgeFaces = pp.edgeFaces();
00990
00991 forAll(edgeFaces, edgeI)
00992 {
00993 const labelList& eFaces = pp.edgeFaces()[edgeI];
00994
00995 label meshEdgeI = meshEdges[edgeI];
00996
00997 forAll(eFaces, i)
00998 {
00999 nomalsCombine()
01000 (
01001 edgeNormal[meshEdgeI],
01002 pp.faceNormals()[eFaces[i]]
01003 );
01004 }
01005 }
01006
01007 syncTools::syncEdgeList
01008 (
01009 mesh,
01010 edgeNormal,
01011 nomalsCombine(),
01012 wallPoint::greatPoint,
01013 false
01014 );
01015
01016 label vertI = 0;
01017 autoPtr<OFstream> str;
01018 if (debug)
01019 {
01020 str.reset(new OFstream(mesh.time().path()/"featureEdges.obj"));
01021 Info<< "Writing feature edges to " << str().name() << endl;
01022 }
01023
01024 label nFeats = 0;
01025
01026
01027
01028 forAll(edgeFaces, edgeI)
01029 {
01030 const labelList& eFaces = pp.edgeFaces()[edgeI];
01031
01032 label meshEdgeI = meshEdges[edgeI];
01033
01034 const vector& n = edgeNormal[meshEdgeI];
01035
01036 if (n != wallPoint::greatPoint)
01037 {
01038 scalar cos = n & pp.faceNormals()[eFaces[0]];
01039
01040 if (cos < minCos)
01041 {
01042 const edge& e = pp.edges()[edgeI];
01043
01044 unmarkExtrusion
01045 (
01046 e[0],
01047 patchDisp,
01048 patchNLayers,
01049 extrudeStatus
01050 );
01051 unmarkExtrusion
01052 (
01053 e[1],
01054 patchDisp,
01055 patchNLayers,
01056 extrudeStatus
01057 );
01058
01059 nFeats++;
01060
01061 if (str.valid())
01062 {
01063 meshTools::writeOBJ(str(), pp.localPoints()[e[0]]);
01064 vertI++;
01065 meshTools::writeOBJ(str(), pp.localPoints()[e[1]]);
01066 vertI++;
01067 str()<< "l " << vertI-1 << ' ' << vertI << nl;
01068 }
01069 }
01070 }
01071 }
01072
01073 Info<< "Set displacement to zero for points on "
01074 << returnReduce(nFeats, sumOp<label>())
01075 << " feature edges" << endl;
01076 }
01077 }
01078
01079
01080
01081
01082
01083
01084 void Foam::autoLayerDriver::handleWarpedFaces
01085 (
01086 const indirectPrimitivePatch& pp,
01087 const scalar faceRatio,
01088 const scalar edge0Len,
01089 const labelList& cellLevel,
01090 pointField& patchDisp,
01091 labelList& patchNLayers,
01092 List<extrudeMode>& extrudeStatus
01093 ) const
01094 {
01095 const fvMesh& mesh = meshRefiner_.mesh();
01096
01097 Info<< nl << "Handling cells with warped patch faces ..." << nl;
01098
01099 const pointField& points = mesh.points();
01100
01101 label nWarpedFaces = 0;
01102
01103 forAll(pp, i)
01104 {
01105 const face& f = pp[i];
01106
01107 if (f.size() > 3)
01108 {
01109 label faceI = pp.addressing()[i];
01110
01111 label ownLevel = cellLevel[mesh.faceOwner()[faceI]];
01112 scalar edgeLen = edge0Len/(1<<ownLevel);
01113
01114
01115 const point& fc = mesh.faceCentres()[faceI];
01116 const vector& fn = pp.faceNormals()[i];
01117
01118 scalarField vProj(f.size());
01119
01120 forAll(f, fp)
01121 {
01122 vector n = points[f[fp]] - fc;
01123 vProj[fp] = (n & fn);
01124 }
01125
01126
01127 scalar minVal = min(vProj);
01128 scalar maxVal = max(vProj);
01129
01130 if ((maxVal - minVal) > faceRatio * edgeLen)
01131 {
01132 if
01133 (
01134 unmarkExtrusion
01135 (
01136 pp.localFaces()[i],
01137 patchDisp,
01138 patchNLayers,
01139 extrudeStatus
01140 )
01141 )
01142 {
01143 nWarpedFaces++;
01144 }
01145 }
01146 }
01147 }
01148
01149 Info<< "Set displacement to zero on "
01150 << returnReduce(nWarpedFaces, sumOp<label>())
01151 << " warped faces since layer would be > " << faceRatio
01152 << " of the size of the bounding box." << endl;
01153 }
01154
01155
01156
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260 void Foam::autoLayerDriver::setNumLayers
01261 (
01262 const labelList& patchToNLayers,
01263 const labelList& patchIDs,
01264 const indirectPrimitivePatch& pp,
01265 pointField& patchDisp,
01266 labelList& patchNLayers,
01267 List<extrudeMode>& extrudeStatus
01268 ) const
01269 {
01270 const fvMesh& mesh = meshRefiner_.mesh();
01271
01272 Info<< nl << "Handling points with inconsistent layer specification ..."
01273 << endl;
01274
01275
01276
01277 labelList maxLayers(patchNLayers.size(), labelMin);
01278 labelList minLayers(patchNLayers.size(), labelMax);
01279
01280 forAll(patchIDs, i)
01281 {
01282 label patchI = patchIDs[i];
01283
01284 const labelList& meshPoints = mesh.boundaryMesh()[patchI].meshPoints();
01285
01286 label wantedLayers = patchToNLayers[patchI];
01287
01288 forAll(meshPoints, patchPointI)
01289 {
01290 label ppPointI = pp.meshPointMap()[meshPoints[patchPointI]];
01291
01292 maxLayers[ppPointI] = max(wantedLayers, maxLayers[ppPointI]);
01293 minLayers[ppPointI] = min(wantedLayers, minLayers[ppPointI]);
01294 }
01295 }
01296
01297 syncTools::syncPointList
01298 (
01299 mesh,
01300 pp.meshPoints(),
01301 maxLayers,
01302 maxEqOp<label>(),
01303 labelMin,
01304 false
01305 );
01306 syncTools::syncPointList
01307 (
01308 mesh,
01309 pp.meshPoints(),
01310 minLayers,
01311 minEqOp<label>(),
01312 labelMax,
01313 false
01314 );
01315
01316
01317
01318
01319
01320
01321 forAll(maxLayers, i)
01322 {
01323 if (maxLayers[i] == labelMin || minLayers[i] == labelMax)
01324 {
01325 FatalErrorIn("setNumLayers(..)")
01326 << "Patchpoint:" << i << " coord:" << pp.localPoints()[i]
01327 << " maxLayers:" << maxLayers
01328 << " minLayers:" << minLayers
01329 << abort(FatalError);
01330 }
01331 else if (maxLayers[i] == minLayers[i])
01332 {
01333
01334 patchNLayers[i] = maxLayers[i];
01335 }
01336 else
01337 {
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352 patchNLayers[i] = maxLayers[i];
01353 }
01354 }
01355
01356
01357
01358
01359
01360
01361 }
01362
01363
01364
01365 void Foam::autoLayerDriver::growNoExtrusion
01366 (
01367 const indirectPrimitivePatch& pp,
01368 pointField& patchDisp,
01369 labelList& patchNLayers,
01370 List<extrudeMode>& extrudeStatus
01371 )
01372 {
01373 Info<< nl << "Growing non-extrusion points by one layer ..." << endl;
01374
01375 List<extrudeMode> grownExtrudeStatus(extrudeStatus);
01376
01377 const faceList& localFaces = pp.localFaces();
01378
01379 label nGrown = 0;
01380
01381 forAll(localFaces, faceI)
01382 {
01383 const face& f = localFaces[faceI];
01384
01385 bool hasSqueeze = false;
01386 forAll(f, fp)
01387 {
01388 if (extrudeStatus[f[fp]] == NOEXTRUDE)
01389 {
01390 hasSqueeze = true;
01391 break;
01392 }
01393 }
01394
01395 if (hasSqueeze)
01396 {
01397
01398 forAll(f, fp)
01399 {
01400 if
01401 (
01402 extrudeStatus[f[fp]] == NOEXTRUDE
01403 && grownExtrudeStatus[f[fp]] != NOEXTRUDE
01404 )
01405 {
01406 grownExtrudeStatus[f[fp]] = NOEXTRUDE;
01407 nGrown++;
01408 }
01409 }
01410 }
01411 }
01412
01413 extrudeStatus.transfer(grownExtrudeStatus);
01414
01415 forAll(extrudeStatus, patchPointI)
01416 {
01417 if (extrudeStatus[patchPointI] == NOEXTRUDE)
01418 {
01419 patchDisp[patchPointI] = vector::zero;
01420 patchNLayers[patchPointI] = 0;
01421 }
01422 }
01423
01424 reduce(nGrown, sumOp<label>());
01425
01426 Info<< "Set displacement to zero for an additional " << nGrown
01427 << " points." << endl;
01428 }
01429
01430
01431 void Foam::autoLayerDriver::calculateLayerThickness
01432 (
01433 const indirectPrimitivePatch& pp,
01434 const labelList& patchIDs,
01435 const scalarField& patchExpansionRatio,
01436
01437 const bool relativeSizes,
01438 const scalarField& patchFinalLayerThickness,
01439 const scalarField& patchMinThickness,
01440
01441 const labelList& cellLevel,
01442 const labelList& patchNLayers,
01443 const scalar edge0Len,
01444
01445 scalarField& thickness,
01446 scalarField& minThickness,
01447 scalarField& expansionRatio
01448 ) const
01449 {
01450 const fvMesh& mesh = meshRefiner_.mesh();
01451 const polyBoundaryMesh& patches = mesh.boundaryMesh();
01452
01453
01454
01455
01456
01457
01458 expansionRatio.setSize(pp.nPoints());
01459 expansionRatio = GREAT;
01460 thickness.setSize(pp.nPoints());
01461 thickness = GREAT;
01462 minThickness.setSize(pp.nPoints());
01463 minThickness = GREAT;
01464
01465 forAll(patchIDs, i)
01466 {
01467 label patchI = patchIDs[i];
01468
01469 const labelList& meshPoints = patches[patchI].meshPoints();
01470
01471 forAll(meshPoints, patchPointI)
01472 {
01473 label ppPointI = pp.meshPointMap()[meshPoints[patchPointI]];
01474
01475 expansionRatio[ppPointI] = min
01476 (
01477 expansionRatio[ppPointI],
01478 patchExpansionRatio[patchI]
01479 );
01480 thickness[ppPointI] = min
01481 (
01482 thickness[ppPointI],
01483 patchFinalLayerThickness[patchI]
01484 );
01485 minThickness[ppPointI] = min
01486 (
01487 minThickness[ppPointI],
01488 patchMinThickness[patchI]
01489 );
01490 }
01491 }
01492
01493 syncTools::syncPointList
01494 (
01495 mesh,
01496 pp.meshPoints(),
01497 expansionRatio,
01498 minEqOp<scalar>(),
01499 GREAT,
01500 false
01501 );
01502 syncTools::syncPointList
01503 (
01504 mesh,
01505 pp.meshPoints(),
01506 thickness,
01507 minEqOp<scalar>(),
01508 GREAT,
01509 false
01510 );
01511 syncTools::syncPointList
01512 (
01513 mesh,
01514 pp.meshPoints(),
01515 minThickness,
01516 minEqOp<scalar>(),
01517 GREAT,
01518 false
01519 );
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530 if (relativeSizes)
01531 {
01532 if (min(patchMinThickness) < 0 || max(patchMinThickness) > 2)
01533 {
01534 FatalErrorIn("calculateLayerThickness(..)")
01535 << "Thickness should be factor of local undistorted cell size."
01536 << " Valid values are [0..2]." << nl
01537 << " minThickness:" << patchMinThickness
01538 << exit(FatalError);
01539 }
01540
01541
01542
01543
01544
01545 labelList maxPointLevel(pp.nPoints(), labelMin);
01546
01547 forAll(pp, i)
01548 {
01549 label ownLevel = cellLevel[mesh.faceOwner()[pp.addressing()[i]]];
01550
01551 const face& f = pp.localFaces()[i];
01552
01553 forAll(f, fp)
01554 {
01555 maxPointLevel[f[fp]] = max(maxPointLevel[f[fp]], ownLevel);
01556 }
01557 }
01558
01559 syncTools::syncPointList
01560 (
01561 mesh,
01562 pp.meshPoints(),
01563 maxPointLevel,
01564 maxEqOp<label>(),
01565 labelMin,
01566 false
01567 );
01568
01569
01570 forAll(maxPointLevel, pointI)
01571 {
01572
01573 scalar edgeLen = edge0Len/(1<<maxPointLevel[pointI]);
01574 thickness[pointI] *= edgeLen;
01575 minThickness[pointI] *= edgeLen;
01576 }
01577 }
01578
01579
01580
01581
01582
01583
01584 forAll(thickness, pointI)
01585 {
01586
01587
01588 if (expansionRatio[pointI] == 1)
01589 {
01590 thickness[pointI] *= patchNLayers[pointI];
01591 }
01592 else
01593 {
01594
01595 scalar invExpansion = 1.0 / expansionRatio[pointI];
01596 label nLay = patchNLayers[pointI];
01597 thickness[pointI] *=
01598 (1.0 - pow(invExpansion, nLay))
01599 / (1.0 - invExpansion);
01600 }
01601 }
01602
01603
01604
01605
01606 }
01607
01608
01609
01610 void Foam::autoLayerDriver::syncPatchDisplacement
01611 (
01612 const motionSmoother& meshMover,
01613 const scalarField& minThickness,
01614 pointField& patchDisp,
01615 labelList& patchNLayers,
01616 List<extrudeMode>& extrudeStatus
01617 ) const
01618 {
01619 const fvMesh& mesh = meshRefiner_.mesh();
01620 const labelList& meshPoints = meshMover.patch().meshPoints();
01621
01622 label nChangedTotal = 0;
01623
01624 while (true)
01625 {
01626 label nChanged = 0;
01627
01628
01629 syncTools::syncPointList
01630 (
01631 mesh,
01632 meshPoints,
01633 patchDisp,
01634 minEqOp<vector>(),
01635 wallPoint::greatPoint,
01636 false
01637 );
01638
01639
01640 forAll(patchDisp, i)
01641 {
01642 if (mag(patchDisp[i]) < minThickness[i])
01643 {
01644 if
01645 (
01646 unmarkExtrusion
01647 (
01648 i,
01649 patchDisp,
01650 patchNLayers,
01651 extrudeStatus
01652 )
01653 )
01654 {
01655 nChanged++;
01656 }
01657 }
01658 }
01659
01660 labelList syncPatchNLayers(patchNLayers);
01661
01662 syncTools::syncPointList
01663 (
01664 mesh,
01665 meshPoints,
01666 syncPatchNLayers,
01667 minEqOp<label>(),
01668 labelMax,
01669 false
01670 );
01671
01672
01673 forAll(syncPatchNLayers, i)
01674 {
01675 if (syncPatchNLayers[i] != patchNLayers[i])
01676 {
01677 if
01678 (
01679 unmarkExtrusion
01680 (
01681 i,
01682 patchDisp,
01683 patchNLayers,
01684 extrudeStatus
01685 )
01686 )
01687 {
01688 nChanged++;
01689 }
01690 }
01691 }
01692
01693 syncTools::syncPointList
01694 (
01695 mesh,
01696 meshPoints,
01697 syncPatchNLayers,
01698 maxEqOp<label>(),
01699 labelMin,
01700 false
01701 );
01702
01703
01704 forAll(syncPatchNLayers, i)
01705 {
01706 if (syncPatchNLayers[i] != patchNLayers[i])
01707 {
01708 if
01709 (
01710 unmarkExtrusion
01711 (
01712 i,
01713 patchDisp,
01714 patchNLayers,
01715 extrudeStatus
01716 )
01717 )
01718 {
01719 nChanged++;
01720 }
01721 }
01722 }
01723 nChangedTotal += nChanged;
01724
01725 if (!returnReduce(nChanged, sumOp<label>()))
01726 {
01727 break;
01728 }
01729 }
01730
01731 Info<< "Prevented extrusion on "
01732 << returnReduce(nChangedTotal, sumOp<label>())
01733 << " coupled patch points during syncPatchDisplacement." << endl;
01734 }
01735
01736
01737
01738
01739
01740
01741
01742 void Foam::autoLayerDriver::getPatchDisplacement
01743 (
01744 const motionSmoother& meshMover,
01745 const scalarField& thickness,
01746 const scalarField& minThickness,
01747 pointField& patchDisp,
01748 labelList& patchNLayers,
01749 List<extrudeMode>& extrudeStatus
01750 ) const
01751 {
01752 Info<< nl << "Determining displacement for added points"
01753 << " according to pointNormal ..." << endl;
01754
01755 const fvMesh& mesh = meshRefiner_.mesh();
01756 const indirectPrimitivePatch& pp = meshMover.patch();
01757 const vectorField& faceNormals = pp.faceNormals();
01758 const labelListList& pointFaces = pp.pointFaces();
01759 const pointField& localPoints = pp.localPoints();
01760 const labelList& meshPoints = pp.meshPoints();
01761
01762
01763
01764
01765 pointField pointNormals(pp.nPoints(), vector::zero);
01766 {
01767 labelList nPointFaces(pp.nPoints(), 0);
01768
01769 forAll(faceNormals, faceI)
01770 {
01771 const face& f = pp.localFaces()[faceI];
01772
01773 forAll(f, fp)
01774 {
01775 pointNormals[f[fp]] += faceNormals[faceI];
01776 nPointFaces[f[fp]] ++;
01777 }
01778 }
01779
01780 syncTools::syncPointList
01781 (
01782 mesh,
01783 meshPoints,
01784 pointNormals,
01785 plusEqOp<vector>(),
01786 vector::zero,
01787 false
01788 );
01789
01790 syncTools::syncPointList
01791 (
01792 mesh,
01793 meshPoints,
01794 nPointFaces,
01795 plusEqOp<label>(),
01796 0,
01797 false
01798 );
01799
01800 forAll(pointNormals, i)
01801 {
01802 pointNormals[i] /= nPointFaces[i];
01803 }
01804 }
01805
01806
01807
01808
01809
01810
01811 patchDisp = thickness*pointNormals;
01812
01813
01814 forAll(pointNormals, patchPointI)
01815 {
01816 label meshPointI = pp.meshPoints()[patchPointI];
01817
01818 if (extrudeStatus[patchPointI] == NOEXTRUDE)
01819 {
01820
01821 patchNLayers[patchPointI] = 0;
01822 patchDisp[patchPointI] = vector::zero;
01823 }
01824 else
01825 {
01826
01827 const vector& n = pointNormals[patchPointI];
01828
01829 if (!meshTools::visNormal(n, faceNormals, pointFaces[patchPointI]))
01830 {
01831 Pout<< "No valid normal for point " << meshPointI
01832 << ' ' << pp.points()[meshPointI]
01833 << "; setting displacement to " << patchDisp[patchPointI]
01834 << endl;
01835
01836 extrudeStatus[patchPointI] = EXTRUDEREMOVE;
01837 }
01838 }
01839 }
01840
01841
01842 forAll(extrudeStatus, patchPointI)
01843 {
01844 if (extrudeStatus[patchPointI] == EXTRUDEREMOVE)
01845 {
01846 point avg(vector::zero);
01847 label nPoints = 0;
01848
01849 const labelList& pEdges = pp.pointEdges()[patchPointI];
01850
01851 forAll(pEdges, i)
01852 {
01853 label edgeI = pEdges[i];
01854
01855 label otherPointI = pp.edges()[edgeI].otherVertex(patchPointI);
01856
01857 if (extrudeStatus[otherPointI] != NOEXTRUDE)
01858 {
01859 avg += localPoints[otherPointI] + patchDisp[otherPointI];
01860 nPoints++;
01861 }
01862 }
01863
01864 if (nPoints > 0)
01865 {
01866 Pout<< "Displacement at illegal point "
01867 << localPoints[patchPointI]
01868 << " set to " << (avg / nPoints - localPoints[patchPointI])
01869 << endl;
01870
01871 patchDisp[patchPointI] =
01872 avg / nPoints
01873 - localPoints[patchPointI];
01874 }
01875 }
01876 }
01877
01878
01879 syncPatchDisplacement
01880 (
01881 meshMover,
01882 minThickness,
01883 patchDisp,
01884 patchNLayers,
01885 extrudeStatus
01886 );
01887
01888 Info<< endl;
01889 }
01890
01891
01892
01893
01894
01895 Foam::label Foam::autoLayerDriver::truncateDisplacement
01896 (
01897 const motionSmoother& meshMover,
01898 const scalarField& minThickness,
01899 const faceSet& illegalPatchFaces,
01900 pointField& patchDisp,
01901 labelList& patchNLayers,
01902 List<extrudeMode>& extrudeStatus
01903 ) const
01904 {
01905 const polyMesh& mesh = meshMover.mesh();
01906 const indirectPrimitivePatch& pp = meshMover.patch();
01907
01908 label nChanged = 0;
01909
01910 const Map<label>& meshPointMap = pp.meshPointMap();
01911
01912 forAllConstIter(faceSet, illegalPatchFaces, iter)
01913 {
01914 label faceI = iter.key();
01915
01916 if (mesh.isInternalFace(faceI))
01917 {
01918 FatalErrorIn("truncateDisplacement(..)")
01919 << "Faceset " << illegalPatchFaces.name()
01920 << " contains internal face " << faceI << nl
01921 << "It should only contain patch faces" << abort(FatalError);
01922 }
01923
01924 const face& f = mesh.faces()[faceI];
01925
01926
01927 forAll(f, fp)
01928 {
01929 if (meshPointMap.found(f[fp]))
01930 {
01931 label patchPointI = meshPointMap[f[fp]];
01932
01933 if (extrudeStatus[patchPointI] != NOEXTRUDE)
01934 {
01935 unmarkExtrusion
01936 (
01937 patchPointI,
01938 patchDisp,
01939 patchNLayers,
01940 extrudeStatus
01941 );
01942 nChanged++;
01943 }
01944 }
01945 }
01946 }
01947
01948 forAll(patchDisp, patchPointI)
01949 {
01950 if (mag(patchDisp[patchPointI]) < minThickness[patchPointI])
01951 {
01952 if
01953 (
01954 unmarkExtrusion
01955 (
01956 patchPointI,
01957 patchDisp,
01958 patchNLayers,
01959 extrudeStatus
01960 )
01961 )
01962 {
01963 nChanged++;
01964 }
01965 }
01966 else if (extrudeStatus[patchPointI] == NOEXTRUDE)
01967 {
01968
01969 patchDisp[patchPointI] = vector::zero;
01970 patchNLayers[patchPointI] = 0;
01971 }
01972 }
01973
01974
01975 const faceList& localFaces = pp.localFaces();
01976
01977 while (true)
01978 {
01979 syncPatchDisplacement
01980 (
01981 meshMover,
01982 minThickness,
01983 patchDisp,
01984 patchNLayers,
01985 extrudeStatus
01986 );
01987
01988
01989
01990
01991
01992 label nPinched = 0;
01993
01994 forAll(localFaces, i)
01995 {
01996 const face& localF = localFaces[i];
01997
01998
01999 label nTrans = 0;
02000
02001 extrudeMode prevMode = extrudeStatus[localF.prevLabel(0)];
02002
02003 forAll(localF, fp)
02004 {
02005 extrudeMode fpMode = extrudeStatus[localF[fp]];
02006
02007 if (prevMode == NOEXTRUDE && fpMode != NOEXTRUDE)
02008 {
02009 nTrans++;
02010 }
02011 prevMode = fpMode;
02012 }
02013
02014 if (nTrans > 1)
02015 {
02016
02017 if
02018 (
02019 unmarkExtrusion
02020 (
02021 localF,
02022 patchDisp,
02023 patchNLayers,
02024 extrudeStatus
02025 )
02026 )
02027 {
02028 nPinched++;
02029 nChanged++;
02030 }
02031 }
02032 }
02033
02034 reduce(nPinched, sumOp<label>());
02035
02036 Info<< "truncateDisplacement : Unextruded " << nPinched
02037 << " faces due to non-consecutive vertices being extruded." << endl;
02038
02039
02040
02041
02042
02043 label nDiffering = 0;
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087 if (nPinched+nDiffering == 0)
02088 {
02089 break;
02090 }
02091 }
02092
02093 return nChanged;
02094 }
02095
02096
02097
02098
02099 void Foam::autoLayerDriver::setupLayerInfoTruncation
02100 (
02101 const motionSmoother& meshMover,
02102 const labelList& patchNLayers,
02103 const List<extrudeMode>& extrudeStatus,
02104 const label nBufferCellsNoExtrude,
02105 labelList& nPatchPointLayers,
02106 labelList& nPatchFaceLayers
02107 ) const
02108 {
02109 Info<< nl << "Setting up information for layer truncation ..." << endl;
02110
02111 const indirectPrimitivePatch& pp = meshMover.patch();
02112 const polyMesh& mesh = meshMover.mesh();
02113
02114 if (nBufferCellsNoExtrude < 0)
02115 {
02116 Info<< nl << "Performing no layer truncation."
02117 << " nBufferCellsNoExtrude set to less than 0 ..." << endl;
02118
02119
02120 forAll(pp.localFaces(), patchFaceI)
02121 {
02122 const face& f = pp.localFaces()[patchFaceI];
02123
02124 forAll(f, fp)
02125 {
02126 if (patchNLayers[f[fp]] > 0)
02127 {
02128 nPatchFaceLayers[patchFaceI] = patchNLayers[f[fp]];
02129 break;
02130 }
02131 }
02132 }
02133 nPatchPointLayers = patchNLayers;
02134 }
02135 else
02136 {
02137
02138 labelList maxLevel(pp.size(), 0);
02139
02140 forAll(pp.localFaces(), patchFaceI)
02141 {
02142 const face& f = pp.localFaces()[patchFaceI];
02143
02144
02145
02146
02147 bool noExtrude = false;
02148 label mLevel = 0;
02149
02150 forAll(f, fp)
02151 {
02152 if (extrudeStatus[f[fp]] == NOEXTRUDE)
02153 {
02154 noExtrude = true;
02155 }
02156 mLevel = max(mLevel, patchNLayers[f[fp]]);
02157 }
02158
02159 if (mLevel > 0)
02160 {
02161
02162
02163
02164 if (noExtrude)
02165 {
02166 nPatchFaceLayers[patchFaceI] = 1;
02167 maxLevel[patchFaceI] = mLevel;
02168 }
02169 else
02170 {
02171 maxLevel[patchFaceI] = mLevel;
02172 }
02173 }
02174 }
02175
02176
02177
02178
02179
02180
02181 const labelListList& pointFaces = pp.pointFaces();
02182
02183 label nLevels = gMax(patchNLayers);
02184
02185
02186 for (label ilevel = 1; ilevel < nLevels; ilevel++)
02187 {
02188 label nBuffer;
02189
02190 if (ilevel == 1)
02191 {
02192 nBuffer = nBufferCellsNoExtrude - 1;
02193 }
02194 else
02195 {
02196 nBuffer = nBufferCellsNoExtrude;
02197 }
02198
02199 for (label ibuffer = 0; ibuffer < nBuffer + 1; ibuffer++)
02200 {
02201 labelList tempCounter(nPatchFaceLayers);
02202
02203 boolList foundNeighbour(pp.nPoints(), false);
02204
02205 forAll(pp.meshPoints(), patchPointI)
02206 {
02207 forAll(pointFaces[patchPointI], pointFaceI)
02208 {
02209 label faceI = pointFaces[patchPointI][pointFaceI];
02210
02211 if
02212 (
02213 nPatchFaceLayers[faceI] != -1
02214 && maxLevel[faceI] > 0
02215 )
02216 {
02217 foundNeighbour[patchPointI] = true;
02218 break;
02219 }
02220 }
02221 }
02222
02223 syncTools::syncPointList
02224 (
02225 mesh,
02226 pp.meshPoints(),
02227 foundNeighbour,
02228 orEqOp<bool>(),
02229 false,
02230 false
02231 );
02232
02233 forAll(pp.meshPoints(), patchPointI)
02234 {
02235 if (foundNeighbour[patchPointI])
02236 {
02237 forAll(pointFaces[patchPointI], pointFaceI)
02238 {
02239 label faceI = pointFaces[patchPointI][pointFaceI];
02240 if
02241 (
02242 nPatchFaceLayers[faceI] == -1
02243 && maxLevel[faceI] > 0
02244 && ilevel < maxLevel[faceI]
02245 )
02246 {
02247 tempCounter[faceI] = ilevel;
02248 }
02249 }
02250 }
02251 }
02252 nPatchFaceLayers = tempCounter;
02253 }
02254 }
02255
02256 forAll(pp.localFaces(), patchFaceI)
02257 {
02258 if (nPatchFaceLayers[patchFaceI] == -1)
02259 {
02260 nPatchFaceLayers[patchFaceI] = maxLevel[patchFaceI];
02261 }
02262 }
02263
02264 forAll(pp.meshPoints(), patchPointI)
02265 {
02266 if (extrudeStatus[patchPointI] != NOEXTRUDE)
02267 {
02268 forAll(pointFaces[patchPointI], pointFaceI)
02269 {
02270 label face = pointFaces[patchPointI][pointFaceI];
02271 nPatchPointLayers[patchPointI] = max
02272 (
02273 nPatchPointLayers[patchPointI],
02274 nPatchFaceLayers[face]
02275 );
02276 }
02277 }
02278 else
02279 {
02280 nPatchPointLayers[patchPointI] = 0;
02281 }
02282 }
02283 syncTools::syncPointList
02284 (
02285 mesh,
02286 pp.meshPoints(),
02287 nPatchPointLayers,
02288 maxEqOp<label>(),
02289 0,
02290 false
02291 );
02292 }
02293 }
02294
02295
02296
02297 bool Foam::autoLayerDriver::cellsUseFace
02298 (
02299 const polyMesh& mesh,
02300 const labelList& cellLabels,
02301 const labelHashSet& faces
02302 )
02303 {
02304 forAll(cellLabels, i)
02305 {
02306 const cell& cFaces = mesh.cells()[cellLabels[i]];
02307
02308 forAll(cFaces, cFaceI)
02309 {
02310 if (faces.found(cFaces[cFaceI]))
02311 {
02312 return true;
02313 }
02314 }
02315 }
02316 return false;
02317 }
02318
02319
02320
02321
02322
02323 Foam::label Foam::autoLayerDriver::checkAndUnmark
02324 (
02325 const addPatchCellLayer& addLayer,
02326 const dictionary& meshQualityDict,
02327 const indirectPrimitivePatch& pp,
02328 const fvMesh& newMesh,
02329
02330 pointField& patchDisp,
02331 labelList& patchNLayers,
02332 List<extrudeMode>& extrudeStatus
02333 )
02334 {
02335
02336 Info<< nl << "Checking mesh with layer ..." << endl;
02337 faceSet wrongFaces(newMesh, "wrongFaces", newMesh.nFaces()/1000);
02338 motionSmoother::checkMesh(false, newMesh, meshQualityDict, wrongFaces);
02339 Info<< "Detected " << returnReduce(wrongFaces.size(), sumOp<label>())
02340 << " illegal faces"
02341 << " (concave, zero area or negative cell pyramid volume)"
02342 << endl;
02343
02344
02345
02346
02347 label nChanged = 0;
02348
02349
02350 labelListList addedCells
02351 (
02352 addPatchCellLayer::addedCells
02353 (
02354 newMesh,
02355 addLayer.layerFaces()
02356 )
02357 );
02358
02359
02360 forAll(addedCells, oldPatchFaceI)
02361 {
02362
02363
02364 const labelList& fCells = addedCells[oldPatchFaceI];
02365
02366 if (cellsUseFace(newMesh, fCells, wrongFaces))
02367 {
02368
02369 if
02370 (
02371 unmarkExtrusion
02372 (
02373 pp.localFaces()[oldPatchFaceI],
02374 patchDisp,
02375 patchNLayers,
02376 extrudeStatus
02377 )
02378 )
02379 {
02380 nChanged++;
02381 }
02382 }
02383 }
02384
02385 return returnReduce(nChanged, sumOp<label>());
02386 }
02387
02388
02389
02390 Foam::label Foam::autoLayerDriver::countExtrusion
02391 (
02392 const indirectPrimitivePatch& pp,
02393 const List<extrudeMode>& extrudeStatus
02394 )
02395 {
02396
02397 label nExtruded = 0;
02398 {
02399 const faceList& localFaces = pp.localFaces();
02400
02401 forAll(localFaces, i)
02402 {
02403 const face& localFace = localFaces[i];
02404
02405 forAll(localFace, fp)
02406 {
02407 if (extrudeStatus[localFace[fp]] != NOEXTRUDE)
02408 {
02409 nExtruded++;
02410 break;
02411 }
02412 }
02413 }
02414 }
02415
02416 return returnReduce(nExtruded, sumOp<label>());
02417 }
02418
02419
02420
02421 void Foam::autoLayerDriver::getLayerCellsFaces
02422 (
02423 const polyMesh& mesh,
02424 const addPatchCellLayer& addLayer,
02425 boolList& flaggedCells,
02426 boolList& flaggedFaces
02427 )
02428 {
02429 flaggedCells.setSize(mesh.nCells());
02430 flaggedCells = false;
02431 flaggedFaces.setSize(mesh.nFaces());
02432 flaggedFaces = false;
02433
02434
02435 const labelListList& layerFaces = addLayer.layerFaces();
02436
02437
02438 labelListList addedCells(addPatchCellLayer::addedCells(mesh, layerFaces));
02439
02440 forAll(addedCells, oldPatchFaceI)
02441 {
02442 const labelList& added = addedCells[oldPatchFaceI];
02443
02444 forAll(added, i)
02445 {
02446 flaggedCells[added[i]] = true;
02447 }
02448 }
02449
02450 forAll(layerFaces, oldPatchFaceI)
02451 {
02452 const labelList& layer = layerFaces[oldPatchFaceI];
02453
02454 if (layer.size())
02455 {
02456 for (label i = 1; i < layer.size()-1; i++)
02457 {
02458 flaggedFaces[layer[i]] = true;
02459 }
02460 }
02461 }
02462 }
02463
02464
02465
02466
02467 Foam::autoLayerDriver::autoLayerDriver(meshRefinement& meshRefiner)
02468 :
02469 meshRefiner_(meshRefiner)
02470 {}
02471
02472
02473
02474
02475 void Foam::autoLayerDriver::mergePatchFacesUndo
02476 (
02477 const layerParameters& layerParams,
02478 const dictionary& motionDict
02479 )
02480 {
02481 scalar minCos = Foam::cos
02482 (
02483 layerParams.featureAngle()
02484 * mathematicalConstant::pi/180.0
02485 );
02486
02487 scalar concaveCos = Foam::cos
02488 (
02489 layerParams.concaveAngle()
02490 * mathematicalConstant::pi/180.0
02491 );
02492
02493 Info<< nl
02494 << "Merging all faces of a cell" << nl
02495 << "---------------------------" << nl
02496 << " - which are on the same patch" << nl
02497 << " - which make an angle < " << layerParams.featureAngle()
02498 << " degrees"
02499 << nl
02500 << " (cos:" << minCos << ')' << nl
02501 << " - as long as the resulting face doesn't become concave"
02502 << " by more than "
02503 << layerParams.concaveAngle() << " degrees" << nl
02504 << " (0=straight, 180=fully concave)" << nl
02505 << endl;
02506
02507 label nChanged = mergePatchFacesUndo(minCos, concaveCos, motionDict);
02508
02509 nChanged += mergeEdgesUndo(minCos, motionDict);
02510 }
02511
02512
02513 void Foam::autoLayerDriver::addLayers
02514 (
02515 const layerParameters& layerParams,
02516 const dictionary& motionDict,
02517 const labelList& patchIDs,
02518 const label nAllowableErrors,
02519 decompositionMethod& decomposer,
02520 fvMeshDistribute& distributor
02521 )
02522 {
02523 fvMesh& mesh = meshRefiner_.mesh();
02524
02525 autoPtr<indirectPrimitivePatch> pp
02526 (
02527 meshRefinement::makePatch
02528 (
02529 mesh,
02530 patchIDs
02531 )
02532 );
02533
02534
02535 Info<< "Constructing mesh displacer ..." << endl;
02536
02537 autoPtr<motionSmoother> meshMover
02538 (
02539 new motionSmoother
02540 (
02541 mesh,
02542 pp(),
02543 patchIDs,
02544 meshRefinement::makeDisplacementField
02545 (
02546 pointMesh::New(mesh),
02547 patchIDs
02548 ),
02549 motionDict
02550 )
02551 );
02552
02553
02554
02555
02556
02557
02558 vectorField patchDisp(pp().nPoints(), vector::one);
02559
02560
02561
02562 labelList patchNLayers(pp().nPoints(), 0);
02563
02564
02565 List<extrudeMode> extrudeStatus(pp().nPoints(), EXTRUDE);
02566
02567 {
02568
02569
02570
02571 setNumLayers
02572 (
02573 layerParams.numLayers(),
02574 meshMover().adaptPatchIDs(),
02575 pp,
02576
02577 patchDisp,
02578 patchNLayers,
02579 extrudeStatus
02580 );
02581
02582
02583 labelList meshEdges(pp().meshEdges(mesh.edges(), mesh.pointEdges()));
02584
02585
02586
02587
02588 handleNonManifolds
02589 (
02590 pp,
02591 meshEdges,
02592
02593 patchDisp,
02594 patchNLayers,
02595 extrudeStatus
02596 );
02597
02598
02599
02600
02601 handleFeatureAngle
02602 (
02603 pp,
02604 meshEdges,
02605 layerParams.featureAngle()*mathematicalConstant::pi/180.0,
02606
02607 patchDisp,
02608 patchNLayers,
02609 extrudeStatus
02610 );
02611
02612
02613
02614
02615
02616 const scalar edge0Len = meshRefiner_.meshCutter().level0EdgeLength();
02617 const labelList& cellLevel = meshRefiner_.meshCutter().cellLevel();
02618
02619 handleWarpedFaces
02620 (
02621 pp,
02622 layerParams.maxFaceThicknessRatio(),
02623 edge0Len,
02624 cellLevel,
02625
02626 patchDisp,
02627 patchNLayers,
02628 extrudeStatus
02629 );
02630
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645 for (label i = 0; i < layerParams.nGrow(); i++)
02646 {
02647 growNoExtrusion
02648 (
02649 pp,
02650 patchDisp,
02651 patchNLayers,
02652 extrudeStatus
02653 );
02654 }
02655 }
02656
02657
02658
02659 const scalar edge0Len = meshRefiner_.meshCutter().level0EdgeLength();
02660 const labelList& cellLevel = meshRefiner_.meshCutter().cellLevel();
02661
02662
02663 scalarField thickness(pp().nPoints());
02664 scalarField minThickness(pp().nPoints());
02665 scalarField expansionRatio(pp().nPoints());
02666 calculateLayerThickness
02667 (
02668 pp,
02669 meshMover().adaptPatchIDs(),
02670 layerParams.expansionRatio(),
02671
02672 layerParams.relativeSizes(),
02673 layerParams.finalLayerThickness(),
02674 layerParams.minThickness(),
02675
02676 cellLevel,
02677 patchNLayers,
02678 edge0Len,
02679
02680 thickness,
02681 minThickness,
02682 expansionRatio
02683 );
02684
02685
02686
02687 {
02688 const polyBoundaryMesh& patches = mesh.boundaryMesh();
02689
02690
02691 label maxPatchNameLen = 0;
02692 forAll(meshMover().adaptPatchIDs(), i)
02693 {
02694 label patchI = meshMover().adaptPatchIDs()[i];
02695 word patchName = patches[patchI].name();
02696 maxPatchNameLen = max(maxPatchNameLen, label(patchName.size()));
02697 }
02698
02699 Info<< nl
02700 << setf(ios_base::left) << setw(maxPatchNameLen) << "patch"
02701 << setw(0) << " faces layers avg thickness[m]" << nl
02702 << setf(ios_base::left) << setw(maxPatchNameLen) << " "
02703 << setw(0) << " near-wall overall" << nl
02704 << setf(ios_base::left) << setw(maxPatchNameLen) << "-----"
02705 << setw(0) << " ----- ------ --------- -------" << endl;
02706
02707 forAll(meshMover().adaptPatchIDs(), i)
02708 {
02709 label patchI = meshMover().adaptPatchIDs()[i];
02710
02711 const labelList& meshPoints = patches[patchI].meshPoints();
02712
02713
02714
02715 scalar sumThickness = 0;
02716 scalar sumNearWallThickness = 0;
02717
02718 forAll(meshPoints, patchPointI)
02719 {
02720 label ppPointI = pp().meshPointMap()[meshPoints[patchPointI]];
02721
02722
02723
02724 sumThickness += thickness[ppPointI];
02725
02726 label nLay = patchNLayers[ppPointI];
02727 if (nLay > 0)
02728 {
02729 if (expansionRatio[ppPointI] == 1)
02730 {
02731 sumNearWallThickness += thickness[ppPointI]/nLay;
02732 }
02733 else
02734 {
02735 scalar s =
02736 (1.0-pow(expansionRatio[ppPointI], nLay))
02737 / (1.0-expansionRatio[ppPointI]);
02738 sumNearWallThickness += thickness[ppPointI]/s;
02739 }
02740 }
02741 }
02742
02743 label totNPoints = returnReduce(meshPoints.size(), sumOp<label>());
02744
02745
02746 scalar avgThickness = 0;
02747 scalar avgNearWallThickness = 0;
02748
02749 if (totNPoints > 0)
02750 {
02751
02752
02753 avgThickness =
02754 returnReduce(sumThickness, sumOp<scalar>())
02755 / totNPoints;
02756 avgNearWallThickness =
02757 returnReduce(sumNearWallThickness, sumOp<scalar>())
02758 / totNPoints;
02759 }
02760
02761 Info<< setf(ios_base::left) << setw(maxPatchNameLen)
02762 << patches[patchI].name() << setprecision(3)
02763 << " " << setw(8)
02764 << returnReduce(patches[patchI].size(), sumOp<scalar>())
02765 << " " << setw(6) << layerParams.numLayers()[patchI]
02766 << " " << setw(8) << avgNearWallThickness
02767 << " " << setw(8) << avgThickness
02768
02769
02770 << endl;
02771 }
02772 Info<< endl;
02773 }
02774
02775
02776
02777
02778
02779 pointScalarField pointMedialDist
02780 (
02781 IOobject
02782 (
02783 "pointMedialDist",
02784 meshRefiner_.timeName(),
02785 mesh,
02786 IOobject::NO_READ,
02787 IOobject::NO_WRITE,
02788 false
02789 ),
02790 meshMover().pMesh(),
02791 dimensionedScalar("pointMedialDist", dimless, 0.0)
02792 );
02793
02794 pointVectorField dispVec
02795 (
02796 IOobject
02797 (
02798 "dispVec",
02799 meshRefiner_.timeName(),
02800 mesh,
02801 IOobject::NO_READ,
02802 IOobject::NO_WRITE,
02803 false
02804 ),
02805 meshMover().pMesh(),
02806 dimensionedVector("dispVec", dimless, vector::zero)
02807 );
02808
02809 pointScalarField medialRatio
02810 (
02811 IOobject
02812 (
02813 "medialRatio",
02814 meshRefiner_.timeName(),
02815 mesh,
02816 IOobject::NO_READ,
02817 IOobject::NO_WRITE,
02818 false
02819 ),
02820 meshMover().pMesh(),
02821 dimensionedScalar("medialRatio", dimless, 0.0)
02822 );
02823
02824
02825
02826
02827
02828
02829
02830 medialAxisSmoothingInfo
02831 (
02832 meshMover,
02833 layerParams.nSmoothNormals(),
02834 layerParams.nSmoothSurfaceNormals(),
02835 layerParams.minMedianAxisAngleCos(),
02836
02837 dispVec,
02838 medialRatio,
02839 pointMedialDist
02840 );
02841
02842
02843
02844
02845 pointField oldPoints(mesh.points());
02846
02847
02848 polyTopoChange savedMeshMod(mesh.boundaryMesh().size());
02849
02850 boolList flaggedCells;
02851 boolList flaggedFaces;
02852
02853 for (label iteration = 0; iteration < layerParams.nLayerIter(); iteration++)
02854 {
02855 Info<< nl
02856 << "Layer addition iteration " << iteration << nl
02857 << "--------------------------" << endl;
02858
02859
02860
02861 const dictionary& meshQualityDict =
02862 (
02863 iteration < layerParams.nRelaxedIter()
02864 ? motionDict
02865 : motionDict.subDict("relaxed")
02866 );
02867
02868 if (iteration >= layerParams.nRelaxedIter())
02869 {
02870 Info<< "Switched to relaxed meshQuality constraints." << endl;
02871 }
02872
02873
02874
02875
02876 syncPatchDisplacement
02877 (
02878 meshMover,
02879 minThickness,
02880 patchDisp,
02881 patchNLayers,
02882 extrudeStatus
02883 );
02884
02885
02886 getPatchDisplacement
02887 (
02888 meshMover,
02889 thickness,
02890 minThickness,
02891 patchDisp,
02892 patchNLayers,
02893 extrudeStatus
02894 );
02895
02896
02897
02898
02899 {
02900 pointField oldPatchPos(pp().localPoints());
02901
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913 shrinkMeshMedialDistance
02914 (
02915 meshMover(),
02916 meshQualityDict,
02917
02918 layerParams.nSmoothThickness(),
02919 layerParams.maxThicknessToMedialRatio(),
02920 nAllowableErrors,
02921 layerParams.nSnap(),
02922 layerParams.layerTerminationCos(),
02923
02924 thickness,
02925 minThickness,
02926
02927 dispVec,
02928 medialRatio,
02929 pointMedialDist,
02930
02931 extrudeStatus,
02932 patchDisp,
02933 patchNLayers
02934 );
02935
02936
02937 patchDisp = oldPatchPos - pp().localPoints();
02938 }
02939
02940
02941
02942 faceSet dummySet(mesh, "wrongPatchFaces", 0);
02943 truncateDisplacement
02944 (
02945 meshMover(),
02946 minThickness,
02947 dummySet,
02948 patchDisp,
02949 patchNLayers,
02950 extrudeStatus
02951 );
02952
02953
02954
02955 if (debug)
02956 {
02957 dumpDisplacement
02958 (
02959 mesh.time().path()/"layer",
02960 pp(),
02961 patchDisp,
02962 extrudeStatus
02963 );
02964
02965 const_cast<Time&>(mesh.time())++;
02966 Info<< "Writing shrunk mesh to " << meshRefiner_.timeName() << endl;
02967
02968
02969
02970
02971 mesh.write();
02972 }
02973
02974
02975
02976 polyTopoChange meshMod(mesh);
02977
02978
02979 addPatchCellLayer addLayer(mesh);
02980
02981
02982
02983
02984 labelList nPatchPointLayers(pp().nPoints(),-1);
02985 labelList nPatchFaceLayers(pp().localFaces().size(),-1);
02986 setupLayerInfoTruncation
02987 (
02988 meshMover(),
02989 patchNLayers,
02990 extrudeStatus,
02991 layerParams.nBufferCellsNoExtrude(),
02992 nPatchPointLayers,
02993 nPatchFaceLayers
02994 );
02995
02996
02997
02998 vectorField firstDisp(patchNLayers.size(), vector::zero);
02999
03000 forAll(patchNLayers, i)
03001 {
03002 if (patchNLayers[i] > 0)
03003 {
03004 if (expansionRatio[i] == 1.0)
03005 {
03006 firstDisp[i] = patchDisp[i]/nPatchPointLayers[i];
03007 }
03008 else
03009 {
03010 label nLay = nPatchPointLayers[i];
03011 scalar h =
03012 pow(expansionRatio[i], nLay - 1)
03013 * (1.0 - expansionRatio[i])
03014 / (1.0 - pow(expansionRatio[i], nLay));
03015 firstDisp[i] = h*patchDisp[i];
03016 }
03017 }
03018 }
03019
03020 scalarField invExpansionRatio = 1.0 / expansionRatio;
03021
03022
03023
03024 addLayer.setRefinement
03025 (
03026 invExpansionRatio,
03027 pp(),
03028 nPatchFaceLayers,
03029 nPatchPointLayers,
03030 firstDisp,
03031 meshMod
03032 );
03033
03034 if (debug)
03035 {
03036 const_cast<Time&>(mesh.time())++;
03037 }
03038
03039
03040 savedMeshMod = meshMod;
03041
03042
03043
03044
03045
03046 autoPtr<fvMesh> newMeshPtr;
03047 autoPtr<mapPolyMesh> map = meshMod.makeMesh
03048 (
03049 newMeshPtr,
03050 IOobject
03051 (
03052
03053 mesh.name(),
03054 static_cast<polyMesh&>(mesh).instance(),
03055 mesh.time(),
03056 static_cast<polyMesh&>(mesh).readOpt(),
03057 static_cast<polyMesh&>(mesh).writeOpt()
03058 ),
03059 mesh,
03060 true
03061 );
03062 fvMesh& newMesh = newMeshPtr();
03063
03064
03065 newMesh.updateMesh(map);
03066
03067 if (meshRefiner_.overwrite())
03068 {
03069 newMesh.setInstance(meshRefiner_.oldInstance());
03070 }
03071
03072
03073
03074
03075 addLayer.updateMesh
03076 (
03077 map,
03078 identity(pp().size()),
03079 identity(pp().nPoints())
03080 );
03081
03082
03083 getLayerCellsFaces
03084 (
03085 newMesh,
03086 addLayer,
03087 flaggedCells,
03088 flaggedFaces
03089 );
03090
03091
03092 if (debug)
03093 {
03094 Info<< "Writing layer mesh to " << meshRefiner_.timeName() << endl;
03095 newMesh.write();
03096 cellSet addedCellSet
03097 (
03098 newMesh,
03099 "addedCells",
03100 findIndices(flaggedCells, true)
03101 );
03102 Info<< "Writing "
03103 << returnReduce(addedCellSet.size(), sumOp<label>())
03104 << " added cells to cellSet "
03105 << addedCellSet.name() << endl;
03106 addedCellSet.write();
03107
03108 faceSet layerFacesSet
03109 (
03110 newMesh,
03111 "layerFaces",
03112 findIndices(flaggedCells, true)
03113 );
03114 Info<< "Writing "
03115 << returnReduce(layerFacesSet.size(), sumOp<label>())
03116 << " faces inside added layer to faceSet "
03117 << layerFacesSet.name() << endl;
03118 layerFacesSet.write();
03119 }
03120
03121
03122 label nTotChanged = checkAndUnmark
03123 (
03124 addLayer,
03125 meshQualityDict,
03126 pp(),
03127 newMesh,
03128
03129 patchDisp,
03130 patchNLayers,
03131 extrudeStatus
03132 );
03133
03134 Info<< "Extruding " << countExtrusion(pp, extrudeStatus)
03135 << " out of " << returnReduce(pp().size(), sumOp<label>())
03136 << " faces. Removed extrusion at " << nTotChanged << " faces."
03137 << endl;
03138
03139 if (nTotChanged == 0)
03140 {
03141 break;
03142 }
03143
03144
03145 meshMover().movePoints(oldPoints);
03146 meshMover().correct();
03147
03148 Info<< endl;
03149 }
03150
03151
03152
03153
03154
03155
03156
03157 autoPtr<mapPolyMesh> map = savedMeshMod.changeMesh(mesh, false);
03158
03159
03160 mesh.updateMesh(map);
03161
03162
03163 if (map().hasMotionPoints())
03164 {
03165 mesh.movePoints(map().preMotionPoints());
03166 }
03167 else
03168 {
03169
03170 mesh.clearOut();
03171 }
03172
03173 if (meshRefiner_.overwrite())
03174 {
03175 mesh.setInstance(meshRefiner_.oldInstance());
03176 }
03177
03178 meshRefiner_.updateMesh(map, labelList(0));
03179
03180
03181
03182
03183
03184 if (Pstream::parRun())
03185 {
03186 Info<< nl
03187 << "Doing final balancing" << nl
03188 << "---------------------" << nl
03189 << endl;
03190
03191 if (debug)
03192 {
03193 const_cast<Time&>(mesh.time())++;
03194 }
03195
03196
03197 autoPtr<mapDistributePolyMesh> map = meshRefiner_.balance
03198 (
03199 false,
03200 false,
03201 scalarField(mesh.nCells(), 1.0),
03202 decomposer,
03203 distributor
03204 );
03205
03206
03207 map().distributeCellData(flaggedCells);
03208 map().distributeFaceData(flaggedFaces);
03209 }
03210
03211
03212
03213
03214
03215 cellSet addedCellSet(mesh, "addedCells", findIndices(flaggedCells, true));
03216 Info<< "Writing "
03217 << returnReduce(addedCellSet.size(), sumOp<label>())
03218 << " added cells to cellSet "
03219 << addedCellSet.name() << endl;
03220 addedCellSet.write();
03221
03222 faceSet layerFacesSet(mesh, "layerFaces", findIndices(flaggedFaces, true));
03223 Info<< "Writing "
03224 << returnReduce(layerFacesSet.size(), sumOp<label>())
03225 << " faces inside added layer to faceSet "
03226 << layerFacesSet.name() << endl;
03227 layerFacesSet.write();
03228 }
03229
03230
03231 void Foam::autoLayerDriver::doLayers
03232 (
03233 const dictionary& shrinkDict,
03234 const dictionary& motionDict,
03235 const layerParameters& layerParams,
03236 const bool preBalance,
03237 decompositionMethod& decomposer,
03238 fvMeshDistribute& distributor
03239 )
03240 {
03241 const fvMesh& mesh = meshRefiner_.mesh();
03242
03243 Info<< nl
03244 << "Shrinking and layer addition phase" << nl
03245 << "----------------------------------" << nl
03246 << endl;
03247
03248 Info<< "Using mesh parameters " << motionDict << nl << endl;
03249
03250
03251 mergePatchFacesUndo(layerParams, motionDict);
03252
03253
03254 const labelList& numLayers = layerParams.numLayers();
03255
03256
03257 DynamicList<label> patchIDs(numLayers.size());
03258 label nFacesWithLayers = 0;
03259 forAll(numLayers, patchI)
03260 {
03261 if (numLayers[patchI] > 0)
03262 {
03263 patchIDs.append(patchI);
03264 nFacesWithLayers += mesh.boundaryMesh()[patchI].size();
03265 }
03266 }
03267 patchIDs.shrink();
03268
03269 if (returnReduce(nFacesWithLayers, sumOp<label>()) == 0)
03270 {
03271 Info<< nl << "No layers to generate ..." << endl;
03272 }
03273 else
03274 {
03275
03276 checkMeshManifold();
03277
03278
03279 Info<< "Checking initial mesh ..." << endl;
03280 labelHashSet wrongFaces(mesh.nFaces()/100);
03281 motionSmoother::checkMesh(false, mesh, motionDict, wrongFaces);
03282 const label nInitErrors = returnReduce
03283 (
03284 wrongFaces.size(),
03285 sumOp<label>()
03286 );
03287
03288 Info<< "Detected " << nInitErrors << " illegal faces"
03289 << " (concave, zero area or negative cell pyramid volume)"
03290 << endl;
03291
03292
03293
03294 if (Pstream::parRun() && preBalance)
03295 {
03296 Info<< nl
03297 << "Doing initial balancing" << nl
03298 << "-----------------------" << nl
03299 << endl;
03300
03301 scalarField cellWeights(mesh.nCells(), 1);
03302 forAll(numLayers, patchI)
03303 {
03304 if (numLayers[patchI] > 0)
03305 {
03306 const polyPatch& pp = mesh.boundaryMesh()[patchI];
03307 forAll(pp.faceCells(), i)
03308 {
03309 cellWeights[pp.faceCells()[i]] += numLayers[patchI];
03310 }
03311 }
03312 }
03313
03314
03315
03316 autoPtr<mapDistributePolyMesh> map = meshRefiner_.balance
03317 (
03318 false,
03319 false,
03320 cellWeights,
03321 decomposer,
03322 distributor
03323 );
03324
03325
03326
03327
03328
03329
03330
03331
03332
03333
03334
03335
03336 }
03337
03338
03339
03340 addLayers
03341 (
03342 layerParams,
03343 motionDict,
03344 patchIDs,
03345 nInitErrors,
03346 decomposer,
03347 distributor
03348 );
03349 }
03350 }
03351
03352
03353