1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 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 volPointInterpolation& pInterp,
48 const GeometricField<Type, fvPatchField, volMesh>& psi
51 interpolation<Type>(psi),
52 psip_(pInterp.interpolate(psi)),
53 psis_(linearInterpolate(psi))
57 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
60 Type interpolationCellPointFace<Type>::interpolate
62 const vector& position,
69 scalar phi[4], phiCandidate[4];
70 label tetLabelCandidate[2], tetPointLabels[2];
72 Type t = pTraits<Type>::zero;
74 // only use face information when the position is on a face
77 const vector& cellCentre = this->pMesh_.cellCentres()[nCell];
78 const labelList& cellFaces = this->pMesh_.cells()[nCell];
80 vector projection = position - cellCentre;
81 tetPoints[3] = cellCentre;
83 // *********************************************************************
84 // project the cell-center through the point onto the face
85 // and get the closest face, ...
86 // *********************************************************************
88 bool foundTet = false;
89 label closestFace = -1;
90 scalar minDistance = GREAT;
92 forAll(cellFaces, facei)
94 label nFace = cellFaces[facei];
96 vector normal = this->pMeshFaceAreas_[nFace];
97 normal /= mag(normal);
99 const vector& faceCentreTmp = this->pMeshFaceCentres_[nFace];
101 scalar multiplierNumerator = (faceCentreTmp - cellCentre) & normal;
102 scalar multiplierDenominator = projection & normal;
104 // if normal and projection are not orthogonal this could be the one...
105 if (mag(multiplierDenominator) > SMALL)
107 scalar multiplier = multiplierNumerator/multiplierDenominator;
108 vector iPoint = cellCentre + multiplier*projection;
109 scalar dist = mag(position - iPoint);
111 if (dist < minDistance)
119 // *********************************************************************
120 // find the tetrahedron containing 'position'
121 // from the cell center, face center and
122 // two other points on the face
123 // *********************************************************************
126 if (closestFace != -1)
128 label nFace = closestFace;
145 // check if the position is 'just' outside a tet
146 if (minDistance < 1.0e-5)
149 for (label i=0; i<4; i++)
151 phi[i] = phiCandidate[i];
153 tetPointLabels[0] = tetLabelCandidate[0];
154 tetPointLabels[1] = tetLabelCandidate[1];
158 // *********************************************************************
159 // if the search failed check all the cell-faces
160 // *********************************************************************
167 while (facei < cellFaces.size() && !foundTet)
169 label nFace = cellFaces[facei];
170 if (nFace < this->pMeshFaceAreas_.size())
191 // check if the position is 'just' outside a tet
192 // this time with a more tolerant limit
193 if (minDistance < 1.0e-3)
196 for (label i=0; i<4; i++)
198 phi[i] = phiCandidate[i];
200 tetPointLabels[0] = tetLabelCandidate[0];
201 tetPointLabels[1] = tetLabelCandidate[1];
205 // *********************************************************************
206 // if the tet was found do the interpolation,
207 // otherwise use the closest face value
208 // *********************************************************************
212 for (label i=0; i<2; i++)
214 ts[i] = psip_[tetPointLabels[i]];
217 if (closestFace < psis_.size())
219 ts[2] = psis_[closestFace];
223 label patchi = this->pMesh_.boundaryMesh().whichPatch(closestFace);
225 // If the boundary patch is not empty use the face value
226 // else use the cell value
227 if (this->psi_.boundaryField()[patchi].size())
229 ts[2] = this->psi_.boundaryField()[patchi]
230 [this->pMesh_.boundaryMesh()[patchi].whichFace(closestFace)];
234 ts[2] = this->psi_[nCell];
238 ts[3] = this->psi_[nCell];
240 for (label n=0; n<4; n++)
242 phi[n] = min(1.0, phi[n]);
243 phi[n] = max(0.0, phi[n]);
250 Info<< "interpolationCellPointFace<Type>::interpolate"
251 << "(const vector&, const label nCell) const : "
252 << "search failed; using closest cellFace value" << endl
253 << "cell number " << nCell << tab
254 << "position " << position << endl;
256 if (closestFace < psis_.size())
258 t = psis_[closestFace];
262 label patchi = this->pMesh_.boundaryMesh().whichPatch(closestFace);
264 // If the boundary patch is not empty use the face value
265 // else use the cell value
266 if (this->psi_.boundaryField()[patchi].size())
268 t = this->psi_.boundaryField()[patchi]
269 [this->pMesh_.boundaryMesh()[patchi].whichFace(closestFace)];
273 t = this->psi_[nCell];
280 bool foundTriangle = findTriangle
290 // add up the point values ...
291 for (label i=0; i<2; i++)
293 Type vel = psip_[tetPointLabels[i]];
297 // ... and the face value
298 if (facei < psis_.size())
300 t += phi[2]*psis_[facei];
304 label patchi = this->pMesh_.boundaryMesh().whichPatch(facei);
306 // If the boundary patch is not empty use the face value
307 // else use the cell value
308 if (this->psi_.boundaryField()[patchi].size())
310 t += phi[2]*this->psi_.boundaryField()[patchi]
311 [this->pMesh_.boundaryMesh()[patchi].whichFace(facei)];
315 t += phi[2]*this->psi_[nCell];
321 // use face value only
322 if (facei < psis_.size())
328 label patchi = this->pMesh_.boundaryMesh().whichPatch(facei);
330 // If the boundary patch is not empty use the face value
331 // else use the cell value
332 if (this->psi_.boundaryField()[patchi].size())
334 t = this->psi_.boundaryField()[patchi]
335 [this->pMesh_.boundaryMesh()[patchi].whichFace(facei)];
339 t = this->psi_[nCell];
349 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
351 } // End namespace Foam
353 // ************************************************************************* //