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
27 \*---------------------------------------------------------------------------*/
29 #include "interpolationCellPointFace.H"
30 #include "volFields.H"
32 #include "volPointInterpolation.H"
34 #include "findCellPointFaceTet.H"
35 #include "findCellPointFaceTriangle.H"
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
42 // * * * * * * * * * * * * * * * * Constructor * * * * * * * * * * * * * * * //
45 interpolationCellPointFace<Type>::interpolationCellPointFace
47 const GeometricField<Type, fvPatchField, volMesh>& psi
50 interpolation<Type>(psi),
51 psip_(volPointInterpolation::New(psi.mesh()).interpolate(psi)),
52 psis_(linearInterpolate(psi))
56 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
59 Type interpolationCellPointFace<Type>::interpolate
61 const vector& position,
68 scalar phi[4], phiCandidate[4];
69 label tetLabelCandidate[2], tetPointLabels[2];
71 Type t = pTraits<Type>::zero;
73 // only use face information when the position is on a face
76 const vector& cellCentre = this->pMesh_.cellCentres()[nCell];
77 const labelList& cellFaces = this->pMesh_.cells()[nCell];
79 vector projection = position - cellCentre;
80 tetPoints[3] = cellCentre;
82 // *********************************************************************
83 // project the cell-center through the point onto the face
84 // and get the closest face, ...
85 // *********************************************************************
87 bool foundTet = false;
88 label closestFace = -1;
89 scalar minDistance = GREAT;
91 forAll(cellFaces, facei)
93 label nFace = cellFaces[facei];
95 vector normal = this->pMeshFaceAreas_[nFace];
96 normal /= mag(normal);
98 const vector& faceCentreTmp = this->pMeshFaceCentres_[nFace];
100 scalar multiplierNumerator = (faceCentreTmp - cellCentre) & normal;
101 scalar multiplierDenominator = projection & normal;
103 // if normal and projection are not orthogonal this could be the one...
104 if (mag(multiplierDenominator) > SMALL)
106 scalar multiplier = multiplierNumerator/multiplierDenominator;
107 vector iPoint = cellCentre + multiplier*projection;
108 scalar dist = mag(position - iPoint);
110 if (dist < minDistance)
118 // *********************************************************************
119 // find the tetrahedron containing 'position'
120 // from the cell center, face center and
121 // two other points on the face
122 // *********************************************************************
125 if (closestFace != -1)
127 label nFace = closestFace;
144 // check if the position is 'just' outside a tet
145 if (minDistance < 1.0e-5)
148 for (label i=0; i<4; i++)
150 phi[i] = phiCandidate[i];
152 tetPointLabels[0] = tetLabelCandidate[0];
153 tetPointLabels[1] = tetLabelCandidate[1];
157 // *********************************************************************
158 // if the search failed check all the cell-faces
159 // *********************************************************************
166 while (facei < cellFaces.size() && !foundTet)
168 label nFace = cellFaces[facei];
169 if (nFace < this->pMeshFaceAreas_.size())
190 // check if the position is 'just' outside a tet
191 // this time with a more tolerant limit
192 if (minDistance < 1.0e-3)
195 for (label i=0; i<4; i++)
197 phi[i] = phiCandidate[i];
199 tetPointLabels[0] = tetLabelCandidate[0];
200 tetPointLabels[1] = tetLabelCandidate[1];
204 // *********************************************************************
205 // if the tet was found do the interpolation,
206 // otherwise use the closest face value
207 // *********************************************************************
211 for (label i=0; i<2; i++)
213 ts[i] = psip_[tetPointLabels[i]];
216 if (closestFace < psis_.size())
218 ts[2] = psis_[closestFace];
222 label patchi = this->pMesh_.boundaryMesh().whichPatch(closestFace);
224 // If the boundary patch is not empty use the face value
225 // else use the cell value
226 if (this->psi_.boundaryField()[patchi].size())
228 ts[2] = this->psi_.boundaryField()[patchi]
229 [this->pMesh_.boundaryMesh()[patchi].whichFace(closestFace)];
233 ts[2] = this->psi_[nCell];
237 ts[3] = this->psi_[nCell];
239 for (label n=0; n<4; n++)
241 phi[n] = min(1.0, phi[n]);
242 phi[n] = max(0.0, phi[n]);
249 Info<< "interpolationCellPointFace<Type>::interpolate"
250 << "(const vector&, const label nCell) const : "
251 << "search failed; using closest cellFace value" << endl
252 << "cell number " << nCell << tab
253 << "position " << position << endl;
255 if (closestFace < psis_.size())
257 t = psis_[closestFace];
261 label patchi = this->pMesh_.boundaryMesh().whichPatch(closestFace);
263 // If the boundary patch is not empty use the face value
264 // else use the cell value
265 if (this->psi_.boundaryField()[patchi].size())
267 t = this->psi_.boundaryField()[patchi]
268 [this->pMesh_.boundaryMesh()[patchi].whichFace(closestFace)];
272 t = this->psi_[nCell];
279 bool foundTriangle = findTriangle
289 // add up the point values ...
290 for (label i=0; i<2; i++)
292 Type vel = psip_[tetPointLabels[i]];
296 // ... and the face value
297 if (facei < psis_.size())
299 t += phi[2]*psis_[facei];
303 label patchi = this->pMesh_.boundaryMesh().whichPatch(facei);
305 // If the boundary patch is not empty use the face value
306 // else use the cell value
307 if (this->psi_.boundaryField()[patchi].size())
309 t += phi[2]*this->psi_.boundaryField()[patchi]
310 [this->pMesh_.boundaryMesh()[patchi].whichFace(facei)];
314 t += phi[2]*this->psi_[nCell];
320 // use face value only
321 if (facei < psis_.size())
327 label patchi = this->pMesh_.boundaryMesh().whichPatch(facei);
329 // If the boundary patch is not empty use the face value
330 // else use the cell value
331 if (this->psi_.boundaryField()[patchi].size())
333 t = this->psi_.boundaryField()[patchi]
334 [this->pMesh_.boundaryMesh()[patchi].whichFace(facei)];
338 t = this->psi_[nCell];
348 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
350 } // End namespace Foam
352 // ************************************************************************* //