1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "motionSmoother.H"
28 #include "meshTools.H"
29 #include "processorPointPatchFields.H"
30 #include "globalPointPatchFields.H"
31 #include "pointConstraint.H"
32 #include "syncTools.H"
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 void Foam::motionSmoother::checkConstraints
39 GeometricField<Type, pointPatchField, pointMesh>& pf
42 typedef GeometricField<Type, pointPatchField, pointMesh> FldType;
44 const polyMesh& mesh = pf.mesh();
46 const polyBoundaryMesh& bm = mesh.boundaryMesh();
48 // first count the total number of patch-patch points
50 label nPatchPatchPoints = 0;
54 if(!isA<emptyPolyPatch>(bm[patchi]))
56 nPatchPatchPoints += bm[patchi].boundaryPoints().size();
61 typename FldType::GeometricBoundaryField& bFld = pf.boundaryField();
64 // Evaluate in reverse order
66 forAllReverse(bFld, patchi)
68 bFld[patchi].initEvaluate(Pstream::blocking); // buffered
71 forAllReverse(bFld, patchi)
73 bFld[patchi].evaluate(Pstream::blocking);
79 Field<Type> boundaryPointValues(nPatchPatchPoints);
80 nPatchPatchPoints = 0;
84 if(!isA<emptyPolyPatch>(bm[patchi]))
86 const labelList& bp = bm[patchi].boundaryPoints();
87 const labelList& meshPoints = bm[patchi].meshPoints();
91 label ppp = meshPoints[bp[pointi]];
92 boundaryPointValues[nPatchPatchPoints++] = pf[ppp];
105 nPatchPatchPoints = 0;
109 if(!isA<emptyPolyPatch>(bm[patchi]))
111 const labelList& bp = bm[patchi].boundaryPoints();
112 const labelList& meshPoints = bm[patchi].meshPoints();
116 label ppp = meshPoints[bp[pointi]];
118 const Type& savedVal = boundaryPointValues[nPatchPatchPoints++];
120 if (savedVal != pf[ppp])
124 "motionSmoother::checkConstraints"
125 "(GeometricField<Type, pointPatchField, pointMesh>&)"
126 ) << "Patch fields are not consistent on mesh point "
127 << ppp << " coordinate " << mesh.points()[ppp]
128 << " at patch " << bm[patchi].name() << '.'
130 << "Reverse evaluation gives value " << savedVal
131 << " , forward evaluation gives value " << pf[ppp]
132 << abort(FatalError);
141 void Foam::motionSmoother::applyCornerConstraints
143 GeometricField<Type, pointPatchField, pointMesh>& pf
146 forAll(patchPatchPointConstraintPoints_, pointi)
148 pf[patchPatchPointConstraintPoints_[pointi]] = transform
150 patchPatchPointConstraintTensors_[pointi],
151 pf[patchPatchPointConstraintPoints_[pointi]]
157 // Average of connected points.
158 template <class Type>
159 Foam::tmp<Foam::GeometricField<Type, Foam::pointPatchField, Foam::pointMesh> >
160 Foam::motionSmoother::avg
162 const GeometricField<Type, pointPatchField, pointMesh>& fld,
163 const scalarField& edgeWeight,
164 const bool separation
167 tmp<GeometricField<Type, pointPatchField, pointMesh> > tres
169 new GeometricField<Type, pointPatchField, pointMesh>
173 "avg("+fld.name()+')',
174 fld.time().timeName(),
180 dimensioned<Type>("zero", fld.dimensions(), pTraits<Type>::zero)
183 GeometricField<Type, pointPatchField, pointMesh>& res = tres();
185 const polyMesh& mesh = fld.mesh()();
188 // Sum local weighted values and weights
189 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
191 // Note: on coupled edges use only one edge (through isMasterEdge)
192 // This is done so coupled edges do not get counted double.
194 scalarField sumWeight(mesh.nPoints(), 0.0);
196 const edgeList& edges = mesh.edges();
200 if (isMasterEdge_.get(edgeI) == 1)
202 const edge& e = edges[edgeI];
203 const scalar w = edgeWeight[edgeI];
205 res[e[0]] += w*fld[e[1]];
206 sumWeight[e[0]] += w;
208 res[e[1]] += w*fld[e[0]];
209 sumWeight[e[1]] += w;
214 // Add coupled contributions
215 // ~~~~~~~~~~~~~~~~~~~~~~~~~
217 syncTools::syncPointList
222 pTraits<Type>::zero, // null value
223 separation // separation
226 syncTools::syncPointList
231 scalar(0), // null value
241 if (mag(sumWeight[pointI]) < VSMALL)
243 // Unconnected point. Take over original value
244 res[pointI] = fld[pointI];
248 res[pointI] /= sumWeight[pointI];
252 res.correctBoundaryConditions();
253 applyCornerConstraints(res);
259 // smooth field (point-jacobi)
260 template <class Type>
261 void Foam::motionSmoother::smooth
263 const GeometricField<Type, pointPatchField, pointMesh>& fld,
264 const scalarField& edgeWeight,
265 const bool separation,
266 GeometricField<Type, pointPatchField, pointMesh>& newFld
269 tmp<pointVectorField> tavgFld = avg
272 edgeWeight, // weighting
273 separation // whether to apply separation vector
275 const pointVectorField& avgFld = tavgFld();
279 if (isInternalPoint(pointI))
281 newFld[pointI] = 0.5*fld[pointI] + 0.5*avgFld[pointI];
285 newFld.correctBoundaryConditions();
286 applyCornerConstraints(newFld);
290 //- Test synchronisation of pointField
291 template<class Type, class CombineOp>
292 void Foam::motionSmoother::testSyncField
294 const Field<Type>& fld,
295 const CombineOp& cop,
297 const bool separation
302 Pout<< "testSyncField : testing synchronisation of Field<Type>."
306 Field<Type> syncedFld(fld);
308 syncTools::syncPointList
314 separation // separation
319 if (syncedFld[i] != fld[i])
323 "motionSmoother::testSyncField"
324 "(const Field<Type>&, const CombineOp&"
325 ", const Type&, const bool)"
326 ) << "On element " << i << " value:" << fld[i]
327 << " synchronised value:" << syncedFld[i]
328 << abort(FatalError);
334 // ************************************************************************* //