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

motionSmootherTemplates.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/meshTools.H>
00028 #include <OpenFOAM/processorPointPatchFields.H>
00029 #include <OpenFOAM/globalPointPatchFields.H>
00030 #include <OpenFOAM/pointConstraint.H>
00031 #include <OpenFOAM/syncTools.H>
00032 
00033 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00034 
00035 template<class Type>
00036 void Foam::motionSmoother::checkConstraints
00037 (
00038     GeometricField<Type, pointPatchField, pointMesh>& pf
00039 )
00040 {
00041     typedef GeometricField<Type, pointPatchField, pointMesh> FldType;
00042 
00043     const polyMesh& mesh = pf.mesh();
00044 
00045     const polyBoundaryMesh& bm = mesh.boundaryMesh();
00046 
00047     // first count the total number of patch-patch points
00048 
00049     label nPatchPatchPoints = 0;
00050 
00051     forAll(bm, patchi)
00052     {
00053         if(!isA<emptyPolyPatch>(bm[patchi]))
00054         {
00055             nPatchPatchPoints += bm[patchi].boundaryPoints().size();
00056         }
00057     }
00058 
00059 
00060     typename FldType::GeometricBoundaryField& bFld = pf.boundaryField();
00061 
00062 
00063     // Evaluate in reverse order
00064 
00065     forAllReverse(bFld, patchi)
00066     {
00067         bFld[patchi].initEvaluate(Pstream::blocking);   // buffered
00068     }
00069 
00070     forAllReverse(bFld, patchi)
00071     {
00072         bFld[patchi].evaluate(Pstream::blocking);
00073     }
00074 
00075 
00076     // Save the values
00077 
00078     Field<Type> boundaryPointValues(nPatchPatchPoints);
00079     nPatchPatchPoints = 0;
00080 
00081     forAll(bm, patchi)
00082     {
00083         if(!isA<emptyPolyPatch>(bm[patchi]))
00084         {
00085             const labelList& bp = bm[patchi].boundaryPoints();
00086             const labelList& meshPoints = bm[patchi].meshPoints();
00087 
00088             forAll(bp, pointi)
00089             {
00090                 label ppp = meshPoints[bp[pointi]];
00091                 boundaryPointValues[nPatchPatchPoints++] = pf[ppp];
00092             }
00093         }
00094     }
00095     
00096 
00097     // Forward evaluation
00098 
00099     bFld.evaluate();
00100 
00101 
00102     // Check
00103 
00104     nPatchPatchPoints = 0;
00105 
00106     forAll(bm, patchi)
00107     {
00108         if(!isA<emptyPolyPatch>(bm[patchi]))
00109         {
00110             const labelList& bp = bm[patchi].boundaryPoints();
00111             const labelList& meshPoints = bm[patchi].meshPoints();
00112 
00113             forAll(bp, pointi)
00114             {
00115                 label ppp = meshPoints[bp[pointi]];
00116 
00117                 const Type& savedVal = boundaryPointValues[nPatchPatchPoints++];
00118 
00119                 if (savedVal != pf[ppp])
00120                 {
00121                     FatalErrorIn
00122                     (
00123                         "motionSmoother::checkConstraints"
00124                         "(GeometricField<Type, pointPatchField, pointMesh>&)"
00125                     )   << "Patch fields are not consistent on mesh point "
00126                         << ppp << " coordinate " << mesh.points()[ppp]
00127                         << " at patch " << bm[patchi].name() << '.'
00128                         << endl
00129                         << "Reverse evaluation gives value " << savedVal
00130                         << " , forward evaluation gives value " << pf[ppp]
00131                         << abort(FatalError);
00132                 }
00133             }
00134         }
00135     }
00136 }
00137 
00138 
00139 template<class Type>
00140 void Foam::motionSmoother::applyCornerConstraints
00141 (
00142     GeometricField<Type, pointPatchField, pointMesh>& pf
00143 ) const
00144 {
00145     forAll(patchPatchPointConstraintPoints_, pointi)
00146     {
00147         pf[patchPatchPointConstraintPoints_[pointi]] = transform
00148         (
00149             patchPatchPointConstraintTensors_[pointi],
00150             pf[patchPatchPointConstraintPoints_[pointi]]
00151         );
00152     }
00153 }
00154 
00155 
00156 // Average of connected points.
00157 template <class Type>
00158 Foam::tmp<Foam::GeometricField<Type, Foam::pointPatchField, Foam::pointMesh> >
00159  Foam::motionSmoother::avg
00160 (
00161     const GeometricField<Type, pointPatchField, pointMesh>& fld,
00162     const scalarField& edgeWeight,
00163     const bool separation
00164 ) const
00165 {
00166     tmp<GeometricField<Type, pointPatchField, pointMesh> > tres
00167     (
00168         new GeometricField<Type, pointPatchField, pointMesh>
00169         (
00170             IOobject
00171             (
00172                 "avg("+fld.name()+')',
00173                 fld.time().timeName(),
00174                 fld.db(),
00175                 IOobject::NO_READ,
00176                 IOobject::NO_WRITE
00177             ),
00178             fld.mesh(),
00179             dimensioned<Type>("zero", fld.dimensions(), pTraits<Type>::zero)
00180         )
00181     );
00182     GeometricField<Type, pointPatchField, pointMesh>& res = tres();
00183 
00184     const polyMesh& mesh = fld.mesh()();
00185 
00186 
00187     // Sum local weighted values and weights
00188     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00189 
00190     // Note: on coupled edges use only one edge (through isMasterEdge)
00191     // This is done so coupled edges do not get counted double.
00192 
00193     scalarField sumWeight(mesh.nPoints(), 0.0);
00194 
00195     const edgeList& edges = mesh.edges();
00196 
00197     forAll(edges, edgeI)
00198     {
00199         if (isMasterEdge_.get(edgeI) == 1)
00200         {
00201             const edge& e = edges[edgeI];
00202             const scalar w = edgeWeight[edgeI];
00203 
00204             res[e[0]] += w*fld[e[1]];
00205             sumWeight[e[0]] += w;
00206 
00207             res[e[1]] += w*fld[e[0]];
00208             sumWeight[e[1]] += w;
00209         }
00210     }
00211 
00212 
00213     // Add coupled contributions
00214     // ~~~~~~~~~~~~~~~~~~~~~~~~~
00215 
00216     syncTools::syncPointList
00217     (
00218         mesh,
00219         res,
00220         plusEqOp<Type>(),
00221         pTraits<Type>::zero,    // null value
00222         separation              // separation
00223     );
00224 
00225     syncTools::syncPointList
00226     (
00227         mesh,
00228         sumWeight,
00229         plusEqOp<scalar>(),
00230         scalar(0),              // null value
00231         false                   // separation
00232     );
00233 
00234 
00235     // Average
00236     // ~~~~~~~
00237 
00238     forAll(res, pointI)
00239     {
00240         if (mag(sumWeight[pointI]) < VSMALL)
00241         {
00242             // Unconnected point. Take over original value
00243             res[pointI] = fld[pointI];
00244         }
00245         else
00246         {
00247             res[pointI] /= sumWeight[pointI];
00248         }
00249     }
00250 
00251     res.correctBoundaryConditions();
00252     applyCornerConstraints(res);
00253 
00254     return tres;
00255 }
00256 
00257 
00258 // smooth field (point-jacobi)
00259 template <class Type>
00260 void Foam::motionSmoother::smooth
00261 (
00262     const GeometricField<Type, pointPatchField, pointMesh>& fld,
00263     const scalarField& edgeWeight,
00264     const bool separation,
00265     GeometricField<Type, pointPatchField, pointMesh>& newFld
00266 ) const
00267 {
00268     tmp<pointVectorField> tavgFld = avg
00269     (
00270         fld,
00271         edgeWeight, // weighting
00272         separation  // whether to apply separation vector
00273     );
00274     const pointVectorField& avgFld = tavgFld();
00275 
00276     forAll(fld, pointI)
00277     {
00278         if (isInternalPoint(pointI))
00279         {
00280             newFld[pointI] = 0.5*fld[pointI] + 0.5*avgFld[pointI];
00281         }
00282     }
00283 
00284     newFld.correctBoundaryConditions();
00285     applyCornerConstraints(newFld);
00286 }
00287 
00288 
00289 //- Test synchronisation of pointField
00290 template<class Type, class CombineOp>
00291 void Foam::motionSmoother::testSyncField
00292 (
00293     const Field<Type>& fld,
00294     const CombineOp& cop,
00295     const Type& zero,
00296     const bool separation,
00297     const scalar maxMag
00298 ) const
00299 {
00300     if (debug)
00301     {
00302         Pout<< "testSyncField : testing synchronisation of Field<Type>."
00303             << endl;
00304     }
00305 
00306     Field<Type> syncedFld(fld);
00307 
00308     syncTools::syncPointList
00309     (
00310         mesh_,
00311         syncedFld,
00312         cop,
00313         zero,       // null value
00314         separation  // separation
00315     );
00316 
00317     forAll(syncedFld, i)
00318     {
00319         if (mag(syncedFld[i] - fld[i]) > maxMag)
00320         {
00321             FatalErrorIn
00322             (
00323                 "motionSmoother::testSyncField"
00324                 "(const Field<Type>&, const CombineOp&"
00325                 ", const Type&, const bool)"
00326             )   << "On element " << i << " value:" << fld[i]
00327                 << " synchronised value:" << syncedFld[i]
00328                 << abort(FatalError);
00329         }
00330     }
00331 }
00332 
00333 
00334 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines