FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

motionSmoother.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "motionSmoother.H"
00027 #include <meshTools/twoDPointCorrector.H>
00028 #include <meshTools/faceSet.H>
00029 #include <meshTools/pointSet.H>
00030 #include <OpenFOAM/fixedValuePointPatchFields.H>
00031 #include <OpenFOAM/pointConstraint.H>
00032 #include <OpenFOAM/syncTools.H>
00033 #include <meshTools/meshTools.H>
00034 #include <OpenFOAM/OFstream.H>
00035 
00036 namespace Foam
00037 {
00038 
00039 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00040 
00041 defineTypeNameAndDebug(motionSmoother, 0);
00042 
00043 }
00044 
00045 
00046 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00047 
00048 // From pointPatchInterpolation
00049 void Foam::motionSmoother::makePatchPatchAddressing()
00050 {
00051     if (debug)
00052     {
00053         Pout<< "motionSmoother::makePatchPatchAddressing() : "
00054             << "constructing boundary addressing"
00055             << endl;
00056     }
00057 
00058     const polyBoundaryMesh& bm = mesh_.boundaryMesh();
00059     const pointBoundaryMesh& pbm = pMesh_.boundary();
00060 
00061     // first count the total number of patch-patch points
00062 
00063     label nPatchPatchPoints = 0;
00064 
00065     forAll(bm, patchi)
00066     {
00067         if(!isA<emptyPolyPatch>(bm[patchi]))
00068         {
00069             nPatchPatchPoints += bm[patchi].boundaryPoints().size();
00070         }
00071     }
00072 
00073 
00074     // Go through all patches and mark up the external edge points
00075     Map<label> patchPatchPointSet(2*nPatchPatchPoints);
00076 
00077     labelList patchPatchPoints(nPatchPatchPoints);
00078 
00079     List<pointConstraint> patchPatchPointConstraints(nPatchPatchPoints);
00080 
00081     label pppi = 0;
00082 
00083     forAll(bm, patchi)
00084     {
00085         if(!isA<emptyPolyPatch>(bm[patchi]))
00086         {
00087             const labelList& bp = bm[patchi].boundaryPoints();
00088             const labelList& meshPoints = bm[patchi].meshPoints();
00089 
00090             forAll(bp, pointi)
00091             {
00092                 label ppp = meshPoints[bp[pointi]];
00093 
00094                 Map<label>::iterator iter = patchPatchPointSet.find(ppp);
00095 
00096                 if (iter == patchPatchPointSet.end())
00097                 {
00098                     patchPatchPointSet.insert(ppp, pppi);
00099                     patchPatchPoints[pppi] = ppp;
00100                     pbm[patchi].applyConstraint
00101                     (
00102                         bp[pointi],
00103                         patchPatchPointConstraints[pppi]
00104                     );
00105                     pppi++;
00106                 }
00107                 else
00108                 {
00109                     pbm[patchi].applyConstraint
00110                     (
00111                         bp[pointi],
00112                         patchPatchPointConstraints[iter()]
00113                     );
00114                 }
00115             }
00116         }
00117     }
00118 
00119     nPatchPatchPoints = pppi;
00120     patchPatchPoints.setSize(nPatchPatchPoints);
00121     patchPatchPointConstraints.setSize(nPatchPatchPoints);
00122 
00123     patchPatchPointConstraintPoints_.setSize(nPatchPatchPoints);
00124     patchPatchPointConstraintTensors_.setSize(nPatchPatchPoints);
00125 
00126     label nConstraints = 0;
00127 
00128     forAll(patchPatchPointConstraints, i)
00129     {
00130         if (patchPatchPointConstraints[i].first() != 0)
00131         {
00132             patchPatchPointConstraintPoints_[nConstraints] =
00133                 patchPatchPoints[i];
00134 
00135             patchPatchPointConstraintTensors_[nConstraints] =
00136                 patchPatchPointConstraints[i].constraintTransformation();
00137 
00138             nConstraints++;
00139         }
00140     }
00141 
00142     patchPatchPointConstraintPoints_.setSize(nConstraints);
00143     patchPatchPointConstraintTensors_.setSize(nConstraints);
00144 
00145 
00146     if (debug)
00147     {
00148         OFstream str(mesh_.db().path()/"constraintPoints.obj");
00149 
00150         Pout<< "Dumping " << patchPatchPointConstraintPoints_.size()
00151             << " constraintPoints to " << str.name() << endl;
00152         forAll(patchPatchPointConstraintPoints_, i)
00153         {
00154             label pointI = patchPatchPointConstraintPoints_[i];
00155 
00156             meshTools::writeOBJ(str, mesh_.points()[pointI]);
00157         }
00158 
00159         Pout<< "motionSmoother::makePatchPatchAddressing() : "
00160             << "finished constructing boundary addressing"
00161             << endl;
00162     }
00163 }
00164 
00165 
00166 void Foam::motionSmoother::checkFld(const pointScalarField& fld)
00167 {
00168     forAll(fld, pointI)
00169     {
00170         const scalar val = fld[pointI];
00171 
00172         if ((val > -GREAT) && (val < GREAT))
00173         {}
00174         else
00175         {
00176             FatalErrorIn("motionSmoother::checkFld")
00177                 << "Problem : point:" << pointI << " value:" << val
00178                 << abort(FatalError);
00179         }
00180     }
00181 }
00182 
00183 
00184 Foam::labelHashSet Foam::motionSmoother::getPoints
00185 (
00186     const labelHashSet& faceLabels
00187 ) const
00188 {
00189     labelHashSet usedPoints(mesh_.nPoints()/100);
00190 
00191     forAllConstIter(labelHashSet, faceLabels, iter)
00192     {
00193         const face& f = mesh_.faces()[iter.key()];
00194 
00195         forAll(f, fp)
00196         {
00197             usedPoints.insert(f[fp]);
00198         }
00199     }
00200 
00201     return usedPoints;
00202 }
00203 
00204 
00205 // Smooth on selected points (usually patch points)
00206 void Foam::motionSmoother::minSmooth
00207 (
00208     const PackedBoolList& isAffectedPoint,
00209     const labelList& meshPoints,
00210     const pointScalarField& fld,
00211     pointScalarField& newFld
00212 ) const
00213 {
00214     tmp<pointScalarField> tavgFld = avg
00215     (
00216         fld,
00217         scalarField(mesh_.nEdges(), 1.0),   // uniform weighting
00218         false                               // fld is not position.
00219     );
00220     const pointScalarField& avgFld = tavgFld();
00221 
00222     forAll(meshPoints, i)
00223     {
00224         label pointI = meshPoints[i];
00225         if (isAffectedPoint.get(pointI) == 1)
00226         {
00227             newFld[pointI] = min
00228             (
00229                 fld[pointI],
00230                 0.5*fld[pointI] + 0.5*avgFld[pointI]
00231             );
00232         }
00233     }
00234 
00235     newFld.correctBoundaryConditions();
00236     applyCornerConstraints(newFld);
00237 }
00238 
00239 
00240 // Smooth on all internal points
00241 void Foam::motionSmoother::minSmooth
00242 (
00243     const PackedBoolList& isAffectedPoint,
00244     const pointScalarField& fld,
00245     pointScalarField& newFld
00246 ) const
00247 {
00248     tmp<pointScalarField> tavgFld = avg
00249     (
00250         fld,
00251         scalarField(mesh_.nEdges(), 1.0),   // uniform weighting
00252         false                               // fld is not position.
00253     );
00254     const pointScalarField& avgFld = tavgFld();
00255 
00256     forAll(fld, pointI)
00257     {
00258         if (isAffectedPoint.get(pointI) == 1 && isInternalPoint(pointI))
00259         {
00260             newFld[pointI] = min
00261             (
00262                 fld[pointI],
00263                 0.5*fld[pointI] + 0.5*avgFld[pointI]
00264             );
00265         }
00266     }
00267 
00268     newFld.correctBoundaryConditions();
00269     applyCornerConstraints(newFld);
00270 }
00271 
00272 
00273 // Scale on selected points
00274 void Foam::motionSmoother::scaleField
00275 (
00276     const labelHashSet& pointLabels,
00277     const scalar scale,
00278     pointScalarField& fld
00279 ) const
00280 {
00281     forAllConstIter(labelHashSet, pointLabels, iter)
00282     {
00283         if (isInternalPoint(iter.key()))
00284         {
00285             fld[iter.key()] *= scale;
00286         }
00287     }
00288     fld.correctBoundaryConditions();
00289     applyCornerConstraints(fld);
00290 }
00291 
00292 
00293 // Scale on selected points (usually patch points)
00294 void Foam::motionSmoother::scaleField
00295 (
00296     const labelList& meshPoints,
00297     const labelHashSet& pointLabels,
00298     const scalar scale,
00299     pointScalarField& fld
00300 ) const
00301 {
00302     forAll(meshPoints, i)
00303     {
00304         label pointI = meshPoints[i];
00305 
00306         if (pointLabels.found(pointI))
00307         {
00308             fld[pointI] *= scale;
00309         }
00310     }
00311 }
00312 
00313 
00314 bool Foam::motionSmoother::isInternalPoint(const label pointI) const
00315 {
00316     return isInternalPoint_.get(pointI) == 1;
00317 }
00318 
00319 
00320 void Foam::motionSmoother::getAffectedFacesAndPoints
00321 (
00322     const label nPointIter,
00323     const faceSet& wrongFaces,
00324 
00325     labelList& affectedFaces,
00326     PackedBoolList& isAffectedPoint
00327 ) const
00328 {
00329     isAffectedPoint.setSize(mesh_.nPoints());
00330     isAffectedPoint = 0;
00331 
00332     faceSet nbrFaces(mesh_, "checkFaces", wrongFaces);
00333 
00334     // Find possible points influenced by nPointIter iterations of
00335     // scaling and smoothing by doing pointCellpoint walk.
00336     // Also update faces-to-be-checked to extend one layer beyond the points
00337     // that will get updated.
00338 
00339     for (label i = 0; i < nPointIter; i++)
00340     {
00341         pointSet nbrPoints(mesh_, "grownPoints", getPoints(nbrFaces.toc()));
00342 
00343         forAllConstIter(pointSet, nbrPoints, iter)
00344         {
00345             const labelList& pCells = mesh_.pointCells(iter.key());
00346 
00347             forAll(pCells, pCellI)
00348             {
00349                 const cell& cFaces = mesh_.cells()[pCells[pCellI]];
00350 
00351                 forAll(cFaces, cFaceI)
00352                 {
00353                     nbrFaces.insert(cFaces[cFaceI]);
00354                 }
00355             }
00356         }
00357         nbrFaces.sync(mesh_);
00358 
00359         if (i == nPointIter - 2)
00360         {
00361             forAllConstIter(faceSet, nbrFaces, iter)
00362             {
00363                 const face& f = mesh_.faces()[iter.key()];
00364                 forAll(f, fp)
00365                 {
00366                     isAffectedPoint.set(f[fp], 1);
00367                 }
00368             }
00369         }
00370     }
00371 
00372     affectedFaces = nbrFaces.toc();
00373 }
00374 
00375 
00376 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00377 
00378 Foam::motionSmoother::motionSmoother
00379 (
00380     polyMesh& mesh,
00381     pointMesh& pMesh,
00382     indirectPrimitivePatch& pp,
00383     const labelList& adaptPatchIDs,
00384     const dictionary& paramDict
00385 )
00386 :
00387     mesh_(mesh),
00388     pMesh_(pMesh),
00389     pp_(pp),
00390     adaptPatchIDs_(adaptPatchIDs),
00391     paramDict_(paramDict),
00392     displacement_
00393     (
00394         IOobject
00395         (
00396             "displacement",
00397             mesh_.time().timeName(),
00398             mesh_,
00399             IOobject::MUST_READ,
00400             IOobject::AUTO_WRITE
00401         ),
00402         pMesh_
00403     ),
00404     scale_
00405     (
00406         IOobject
00407         (
00408             "scale",
00409             mesh_.time().timeName(),
00410             mesh_,
00411             IOobject::NO_READ,
00412             IOobject::AUTO_WRITE
00413         ),
00414         pMesh_,
00415         dimensionedScalar("scale", dimless, 1.0)
00416     ),
00417     oldPoints_(mesh_.points()),
00418     isInternalPoint_(mesh_.nPoints(), 1),
00419     twoDCorrector_(mesh_)
00420 {
00421     updateMesh();
00422 }
00423 
00424 
00425 Foam::motionSmoother::motionSmoother
00426 (
00427     polyMesh& mesh,
00428     indirectPrimitivePatch& pp,
00429     const labelList& adaptPatchIDs,
00430     const pointVectorField& displacement,
00431     const dictionary& paramDict
00432 )
00433 :
00434     mesh_(mesh),
00435     pMesh_(const_cast<pointMesh&>(displacement.mesh())),
00436     pp_(pp),
00437     adaptPatchIDs_(adaptPatchIDs),
00438     paramDict_(paramDict),
00439     displacement_
00440     (
00441         IOobject
00442         (
00443             "displacement",
00444             mesh_.time().timeName(),
00445             mesh_,
00446             IOobject::NO_READ,
00447             IOobject::AUTO_WRITE
00448         ),
00449         displacement
00450     ),
00451     scale_
00452     (
00453         IOobject
00454         (
00455             "scale",
00456             mesh_.time().timeName(),
00457             mesh_,
00458             IOobject::NO_READ,
00459             IOobject::AUTO_WRITE
00460         ),
00461         pMesh_,
00462         dimensionedScalar("scale", dimless, 1.0)
00463     ),
00464     oldPoints_(mesh_.points()),
00465     isInternalPoint_(mesh_.nPoints(), 1),
00466     twoDCorrector_(mesh_)
00467 {
00468     updateMesh();
00469 }
00470 
00471 
00472 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00473 
00474 Foam::motionSmoother::~motionSmoother()
00475 {}
00476 
00477 
00478 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00479 
00480 const Foam::polyMesh& Foam::motionSmoother::mesh() const
00481 {
00482     return mesh_;
00483 }
00484 
00485 
00486 const Foam::pointMesh& Foam::motionSmoother::pMesh() const
00487 {
00488     return pMesh_;
00489 }
00490 
00491 
00492 const Foam::indirectPrimitivePatch& Foam::motionSmoother::patch() const
00493 {
00494     return pp_;
00495 }
00496 
00497 
00498 const Foam::labelList& Foam::motionSmoother::adaptPatchIDs() const
00499 {
00500     return adaptPatchIDs_;
00501 }
00502 
00503 
00504 const Foam::dictionary& Foam::motionSmoother::paramDict() const
00505 {
00506     return paramDict_;
00507 }
00508 
00509 
00510 Foam::pointVectorField& Foam::motionSmoother::displacement()
00511 {
00512     return displacement_;
00513 }
00514 
00515 
00516 const Foam::pointVectorField& Foam::motionSmoother::displacement() const
00517 {
00518     return displacement_;
00519 }
00520 
00521 
00522 const Foam::pointScalarField& Foam::motionSmoother::scale() const
00523 {
00524     return scale_;
00525 }
00526 
00527 
00528 const Foam::pointField& Foam::motionSmoother::oldPoints() const
00529 {
00530     return oldPoints_;
00531 }
00532 
00533 
00534 void Foam::motionSmoother::correct()
00535 {
00536     oldPoints_ = mesh_.points();
00537 
00538     scale_ = 1.0;
00539 
00540     // No need to update twoDmotion corrector since only holds edge labels
00541     // which will remain the same as before. So unless the mesh was distorted
00542     // severely outside of motionSmoother there will be no need.
00543 }
00544 
00545 
00546 void Foam::motionSmoother::setDisplacement(pointField& patchDisp)
00547 {
00548     // See comment in .H file about shared points.
00549     const polyBoundaryMesh& patches = mesh_.boundaryMesh();
00550 
00551     forAll(patches, patchI)
00552     {
00553         const polyPatch& pp = patches[patchI];
00554 
00555         if (pp.coupled())
00556         {
00557             const labelList& meshPoints = pp.meshPoints();
00558 
00559             forAll(meshPoints, i)
00560             {
00561                 displacement_[meshPoints[i]] = vector::zero;
00562             }
00563         }
00564     }
00565 
00566     const labelList& ppMeshPoints = pp_.meshPoints();
00567 
00568     // Set internal point data from displacement on combined patch points.
00569     forAll(ppMeshPoints, patchPointI)
00570     {
00571         displacement_[ppMeshPoints[patchPointI]] = patchDisp[patchPointI];
00572     }
00573 
00574     // Adapt the fixedValue bc's (i.e. copy internal point data to
00575     // boundaryField for all affected patches)
00576     forAll(adaptPatchIDs_, i)
00577     {
00578         label patchI = adaptPatchIDs_[i];
00579 
00580         displacement_.boundaryField()[patchI] ==
00581             displacement_.boundaryField()[patchI].patchInternalField();
00582     }
00583 
00584     // Make consistent with non-adapted bc's by evaluating those now and
00585     // resetting the displacement from the values.
00586     // Note that we're just doing a correctBoundaryConditions with
00587     // fixedValue bc's first.
00588     labelHashSet adaptPatchSet(adaptPatchIDs_);
00589 
00590     const lduSchedule& patchSchedule = mesh_.globalData().patchSchedule();
00591 
00592     forAll(patchSchedule, patchEvalI)
00593     {
00594         label patchI = patchSchedule[patchEvalI].patch;
00595 
00596         if (!adaptPatchSet.found(patchI))
00597         {
00598             if (patchSchedule[patchEvalI].init)
00599             {
00600                 displacement_.boundaryField()[patchI]
00601                     .initEvaluate(Pstream::scheduled);
00602             }
00603             else
00604             {
00605                 displacement_.boundaryField()[patchI]
00606                     .evaluate(Pstream::scheduled);
00607             }
00608         }
00609     }
00610 
00611     // Multi-patch constraints
00612     applyCornerConstraints(displacement_);
00613 
00614     // Correct for problems introduced by corner constraints
00615     syncTools::syncPointList
00616     (
00617         mesh_,
00618         displacement_,
00619         maxMagEqOp(),   // combine op
00620         vector::zero,   // null value
00621         false           // no separation
00622     );
00623 
00624     // Adapt the fixedValue bc's (i.e. copy internal point data to
00625     // boundaryField for all affected patches) to take the changes caused
00626     // by multi-corner constraints into account.
00627     forAll(adaptPatchIDs_, i)
00628     {
00629         label patchI = adaptPatchIDs_[i];
00630 
00631         displacement_.boundaryField()[patchI] ==
00632             displacement_.boundaryField()[patchI].patchInternalField();
00633     }
00634 
00635     if (debug)
00636     {
00637         OFstream str(mesh_.db().path()/"changedPoints.obj");
00638         label nVerts = 0;
00639         forAll(ppMeshPoints, patchPointI)
00640         {
00641             const vector& newDisp = displacement_[ppMeshPoints[patchPointI]];
00642 
00643             if (mag(newDisp-patchDisp[patchPointI]) > SMALL)
00644             {
00645                 const point& pt = mesh_.points()[ppMeshPoints[patchPointI]];
00646 
00647                 meshTools::writeOBJ(str, pt);
00648                 nVerts++;
00649                 //Pout<< "Point:" << pt
00650                 //    << " oldDisp:" << patchDisp[patchPointI]
00651                 //    << " newDisp:" << newDisp << endl;
00652             }
00653         }
00654         Pout<< "Written " << nVerts << " points that are changed to file "
00655             << str.name() << endl;
00656     }
00657 
00658     // Now reset input displacement
00659     forAll(ppMeshPoints, patchPointI)
00660     {
00661         patchDisp[patchPointI] = displacement_[ppMeshPoints[patchPointI]];
00662     }
00663 }
00664 
00665 
00666 // correctBoundaryConditions with fixedValue bc's first.
00667 void Foam::motionSmoother::correctBoundaryConditions
00668 (
00669     pointVectorField& displacement
00670 ) const
00671 {
00672     labelHashSet adaptPatchSet(adaptPatchIDs_);
00673 
00674     const lduSchedule& patchSchedule = mesh_.globalData().patchSchedule();
00675 
00676     // 1. evaluate on adaptPatches
00677     forAll(patchSchedule, patchEvalI)
00678     {
00679         label patchI = patchSchedule[patchEvalI].patch;
00680 
00681         if (adaptPatchSet.found(patchI))
00682         {
00683             if (patchSchedule[patchEvalI].init)
00684             {
00685                 displacement.boundaryField()[patchI]
00686                     .initEvaluate(Pstream::blocking);
00687             }
00688             else
00689             {
00690                 displacement.boundaryField()[patchI]
00691                     .evaluate(Pstream::blocking);
00692             }
00693         }
00694     }
00695 
00696 
00697     // 2. evaluate on non-AdaptPatches
00698     forAll(patchSchedule, patchEvalI)
00699     {
00700         label patchI = patchSchedule[patchEvalI].patch;
00701 
00702         if (!adaptPatchSet.found(patchI))
00703         {
00704             if (patchSchedule[patchEvalI].init)
00705             {
00706                 displacement.boundaryField()[patchI]
00707                     .initEvaluate(Pstream::blocking);
00708             }
00709             else
00710             {
00711                 displacement.boundaryField()[patchI]
00712                     .evaluate(Pstream::blocking);
00713             }
00714         }
00715     }
00716 
00717     // Multi-patch constraints
00718     applyCornerConstraints(displacement);
00719 
00720     // Correct for problems introduced by corner constraints
00721     syncTools::syncPointList
00722     (
00723         mesh_,
00724         displacement,
00725         maxMagEqOp(),           // combine op
00726         vector::zero,           // null value
00727         false                   // no separation
00728     );
00729 }
00730 
00731 
00732 Foam::tmp<Foam::scalarField> Foam::motionSmoother::movePoints
00733 (
00734     pointField& newPoints
00735 )
00736 {
00737     // Correct for 2-D motion
00738     if (twoDCorrector_.required())
00739     {
00740         Info<< "Correct-ing 2-D mesh motion";
00741 
00742         if (mesh_.globalData().parallel())
00743         {
00744             WarningIn("motionSmoother::movePoints(pointField& newPoints)")
00745                 << "2D mesh-motion probably not correct in parallel" << endl;
00746         }
00747 
00748         // We do not want to move 3D planes so project all points onto those
00749         const pointField& oldPoints = mesh_.points();
00750         const edgeList& edges = mesh_.edges();
00751 
00752         const labelList& neIndices = twoDCorrector().normalEdgeIndices();
00753         const vector& pn = twoDCorrector().planeNormal();
00754 
00755         forAll(neIndices, i)
00756         {
00757             const edge& e = edges[neIndices[i]];
00758 
00759             point& pStart = newPoints[e.start()];
00760 
00761             pStart += pn*(pn & (oldPoints[e.start()] - pStart));
00762 
00763             point& pEnd = newPoints[e.end()];
00764 
00765             pEnd += pn*(pn & (oldPoints[e.end()] - pEnd));
00766         }
00767 
00768         // Correct tangentially
00769         twoDCorrector_.correctPoints(newPoints);
00770         Info<< " ...done" << endl;
00771     }
00772 
00773     if (debug)
00774     {
00775         Pout<< "motionSmoother::movePoints : testing sync of newPoints."
00776             << endl;
00777         testSyncField
00778         (
00779             newPoints,
00780             minEqOp<point>(),           // combine op
00781             vector(GREAT,GREAT,GREAT),  // null
00782             true,                       // separation
00783             1E-6*mesh_.bounds().mag()
00784         );
00785     }
00786 
00787     tmp<scalarField> tsweptVol = mesh_.movePoints(newPoints);
00788 
00789     pp_.movePoints(mesh_.points());
00790 
00791     return tsweptVol;
00792 }
00793 
00794 
00795 Foam::scalar Foam::motionSmoother::setErrorReduction
00796 (
00797     const scalar errorReduction
00798 )
00799 {
00800     scalar oldErrorReduction = readScalar(paramDict_.lookup("errorReduction"));
00801 
00802     paramDict_.remove("errorReduction");
00803     paramDict_.add("errorReduction", errorReduction);
00804 
00805     return oldErrorReduction;
00806 }
00807 
00808 
00809 bool Foam::motionSmoother::scaleMesh
00810 (
00811     labelList& checkFaces,
00812     const bool smoothMesh,
00813     const label nAllowableErrors
00814 )
00815 {
00816     List<labelPair> emptyBaffles;
00817     return scaleMesh
00818     (
00819         checkFaces,
00820         emptyBaffles,
00821         smoothMesh,
00822         nAllowableErrors
00823     );
00824 }
00825 
00826 
00827 bool Foam::motionSmoother::scaleMesh
00828 (
00829     labelList& checkFaces,
00830     const List<labelPair>& baffles,
00831     const bool smoothMesh,
00832     const label nAllowableErrors
00833 )
00834 {
00835     return scaleMesh
00836     (
00837         checkFaces,
00838         baffles,
00839         paramDict_,
00840         paramDict_,
00841         smoothMesh,
00842         nAllowableErrors
00843     );
00844 }
00845 
00846 
00847 bool Foam::motionSmoother::scaleMesh
00848 (
00849     labelList& checkFaces,
00850     const List<labelPair>& baffles,
00851     const dictionary& paramDict,
00852     const dictionary& meshQualityDict,
00853     const bool smoothMesh,
00854     const label nAllowableErrors
00855 )
00856 {
00857     if (!smoothMesh && adaptPatchIDs_.empty())
00858     {
00859         FatalErrorIn("motionSmoother::scaleMesh(const bool")
00860             << "You specified both no movement on the internal mesh points"
00861             << " (smoothMesh = false)" << nl
00862             << "and no movement on the patch (adaptPatchIDs is empty)" << nl
00863             << "Hence nothing to adapt."
00864             << exit(FatalError);
00865     }
00866 
00867     if (debug)
00868     {
00869         // Had a problem with patches moved non-synced. Check transformations.
00870         const polyBoundaryMesh& patches = mesh_.boundaryMesh();
00871 
00872         Pout<< "Entering scaleMesh : coupled patches:" << endl;
00873         forAll(patches, patchI)
00874         {
00875             if (patches[patchI].coupled())
00876             {
00877                 const coupledPolyPatch& pp =
00878                     refCast<const coupledPolyPatch>(patches[patchI]);
00879 
00880                 Pout<< '\t' << patchI << '\t' << pp.name()
00881                     << " parallel:" << pp.parallel()
00882                     << " separated:" << pp.separated()
00883                     << " forwardT:" << pp.forwardT().size()
00884                     << endl;
00885             }
00886         }
00887     }
00888 
00889     const scalar errorReduction =
00890         readScalar(paramDict.lookup("errorReduction"));
00891     const label nSmoothScale =
00892         readLabel(paramDict.lookup("nSmoothScale"));
00893 
00894 
00895     // Note: displacement_ should already be synced already from setDisplacement
00896     // but just to make sure.
00897     syncTools::syncPointList
00898     (
00899         mesh_,
00900         displacement_,
00901         maxMagEqOp(),
00902         vector::zero,   // null value
00903         false           // no separation
00904     );
00905 
00906     // Set newPoints as old + scale*displacement
00907     pointField newPoints;
00908     {
00909         // Create overall displacement with same b.c.s as displacement_
00910         pointVectorField totalDisplacement
00911         (
00912             IOobject
00913             (
00914                 "totalDisplacement",
00915                 mesh_.time().timeName(),
00916                 mesh_,
00917                 IOobject::NO_READ,
00918                 IOobject::NO_WRITE,
00919                 false
00920             ),
00921             scale_*displacement_,
00922             displacement_.boundaryField().types()
00923         );
00924         correctBoundaryConditions(totalDisplacement);
00925 
00926         if (debug)
00927         {
00928             Pout<< "scaleMesh : testing sync of totalDisplacement" << endl;
00929             testSyncField
00930             (
00931                 totalDisplacement,
00932                 maxMagEqOp(),
00933                 vector::zero,   // null value
00934                 false,          // separation
00935                 1E-6*mesh_.bounds().mag()
00936             );
00937         }
00938 
00939         newPoints = oldPoints_ + totalDisplacement.internalField();
00940     }
00941 
00942     Info<< "Moving mesh using diplacement scaling :"
00943         << " min:" << gMin(scale_.internalField())
00944         << "  max:" << gMax(scale_.internalField())
00945         << endl;
00946 
00947 
00948     // Move
00949     movePoints(newPoints);
00950 
00951     // Check. Returns parallel number of incorrect faces.
00952     faceSet wrongFaces(mesh_, "wrongFaces", mesh_.nFaces()/100+100);
00953     checkMesh(false, mesh_, meshQualityDict, checkFaces, baffles, wrongFaces);
00954 
00955     if (returnReduce(wrongFaces.size(), sumOp<label>()) <= nAllowableErrors)
00956     {
00957         return true;
00958     }
00959     else
00960     {
00961         // Sync across coupled faces by extending the set.
00962         wrongFaces.sync(mesh_);
00963 
00964         // Special case:
00965         // if errorReduction is set to zero, extend wrongFaces
00966         // to face-Cell-faces to ensure quick return to previously valid mesh
00967 
00968         if (mag(errorReduction) < SMALL)
00969         {
00970             labelHashSet newWrongFaces(wrongFaces);
00971             forAllConstIter(labelHashSet, wrongFaces, iter)
00972             {
00973                 label own = mesh_.faceOwner()[iter.key()];
00974                 const cell& ownFaces = mesh_.cells()[own];
00975 
00976                 forAll(ownFaces, cfI)
00977                 {
00978                     newWrongFaces.insert(ownFaces[cfI]);
00979                 }
00980 
00981                 if (iter.key() < mesh_.nInternalFaces())
00982                 {
00983                     label nei = mesh_.faceNeighbour()[iter.key()];
00984                     const cell& neiFaces = mesh_.cells()[nei];
00985 
00986                     forAll(neiFaces, cfI)
00987                     {
00988                         newWrongFaces.insert(neiFaces[cfI]);
00989                     }
00990                 }
00991             }
00992             wrongFaces.transfer(newWrongFaces);
00993             wrongFaces.sync(mesh_);
00994         }
00995 
00996 
00997         // Find out points used by wrong faces and scale displacement.
00998         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00999 
01000         pointSet usedPoints(mesh_, "usedPoints", getPoints(wrongFaces));
01001         usedPoints.sync(mesh_);
01002 
01003 
01004 
01005         // Grow a few layers to determine
01006         // - points to be smoothed
01007         // - faces to be checked in next iteration
01008         PackedBoolList isAffectedPoint(mesh_.nPoints());
01009         getAffectedFacesAndPoints
01010         (
01011             nSmoothScale,       // smoothing iterations
01012             wrongFaces,         // error faces
01013             checkFaces,
01014             isAffectedPoint
01015         );
01016 
01017         if (debug)
01018         {
01019             Pout<< "Faces in error:" << wrongFaces.size()
01020                 << "  with points:" << usedPoints.size()
01021                 << endl;
01022         }
01023 
01024         if (adaptPatchIDs_.size())
01025         {
01026             // Scale conflicting patch points
01027             scaleField(pp_.meshPoints(), usedPoints, errorReduction, scale_);
01028         }
01029         if (smoothMesh)
01030         {
01031             // Scale conflicting internal points
01032             scaleField(usedPoints, errorReduction, scale_);
01033         }
01034 
01035         for (label i = 0; i < nSmoothScale; i++)
01036         {
01037             if (adaptPatchIDs_.size())
01038             {
01039                 // Smooth patch values
01040                 pointScalarField oldScale(scale_);
01041                 minSmooth
01042                 (
01043                     isAffectedPoint,
01044                     pp_.meshPoints(),
01045                     oldScale,
01046                     scale_
01047                 );
01048                 checkFld(scale_);
01049             }
01050             if (smoothMesh)
01051             {
01052                 // Smooth internal values
01053                 pointScalarField oldScale(scale_);
01054                 minSmooth(isAffectedPoint, oldScale, scale_);
01055                 checkFld(scale_);
01056             }
01057         }
01058 
01059         syncTools::syncPointList
01060         (
01061             mesh_,
01062             scale_,
01063             maxEqOp<scalar>(),
01064             -GREAT,             // null value
01065             false               // no separation
01066         );
01067 
01068 
01069         if (debug)
01070         {
01071             Pout<< "scale_ after smoothing :"
01072                 << " min:" << Foam::gMin(scale_)
01073                 << " max:" << Foam::gMax(scale_)
01074                 << endl;
01075         }
01076 
01077         return false;
01078     }
01079 }
01080 
01081 
01082 void Foam::motionSmoother::updateMesh()
01083 {
01084     const pointBoundaryMesh& patches = pMesh_.boundary();
01085 
01086     // Check whether displacement has fixed value b.c. on adaptPatchID
01087     forAll(adaptPatchIDs_, i)
01088     {
01089         label patchI = adaptPatchIDs_[i];
01090 
01091         if
01092         (
01093            !isA<fixedValuePointPatchVectorField>
01094             (
01095                 displacement_.boundaryField()[patchI]
01096             )
01097         )
01098         {
01099             FatalErrorIn
01100             (
01101                 "motionSmoother::motionSmoother"
01102             )   << "Patch " << patches[patchI].name()
01103                 << " has wrong boundary condition "
01104                 << displacement_.boundaryField()[patchI].type()
01105                 << " on field " << displacement_.name() << nl
01106                 << "Only type allowed is "
01107                 << fixedValuePointPatchVectorField::typeName
01108                 << exit(FatalError);
01109         }
01110     }
01111 
01112 
01113     // Determine internal points. Note that for twoD there are no internal
01114     // points so we use the points of adaptPatchIDs instead
01115 
01116     twoDCorrector_.updateMesh();
01117 
01118     const labelList& meshPoints = pp_.meshPoints();
01119 
01120     forAll(meshPoints, i)
01121     {
01122         isInternalPoint_.set(meshPoints[i], 0);
01123     }
01124 
01125     // Calculate master edge addressing
01126     isMasterEdge_ = syncTools::getMasterEdges(mesh_);
01127 
01128     makePatchPatchAddressing();
01129 }
01130 
01131 
01132 // Specialisation of applyCornerConstraints for scalars because
01133 // no constraint need be applied
01134 template<>
01135 void Foam::motionSmoother::applyCornerConstraints<Foam::scalar>
01136 (
01137     GeometricField<scalar, pointPatchField, pointMesh>& pf
01138 ) const
01139 {}
01140 
01141 
01142 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines