pointMVCWeight.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2025 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
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
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "pointMVCWeight.H"
27 #include "polyMesh.H"
28 
29 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
30 
31 namespace Foam
32 {
34 }
35 
36 
37 Foam::scalar Foam::pointMVCWeight::tol(small);
38 
39 
40 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
41 
43 (
44  const Map<label>& toLocal,
45  const face& f,
46  const DynamicList<point>& u,
47  const scalarField& dist,
48  scalarField& weights
49 ) const
50 {
51  weights.setSize(toLocal.size());
52  weights = 0.0;
53 
54  scalarField theta(f.size());
55 
56  // recompute theta, the theta computed previously are not robust
57  forAll(f, j)
58  {
59  label jPlus1 = f.fcIndex(j);
60  scalar l = mag(u[j] - u[jPlus1]);
61  theta[j] = 2.0*Foam::asin(l/2.0);
62  }
63 
64  scalar sumWeight = 0;
65  forAll(f, j)
66  {
67  label pid = toLocal[f[j]];
68  label jMin1 = f.rcIndex(j);
69  weights[pid] =
70  1.0
71  / dist[pid]
72  * (Foam::tan(theta[jMin1]/2.0) + Foam::tan(theta[j]/2.0));
73  sumWeight += weights[pid];
74  }
75 
76  if (sumWeight >= tol)
77  {
78  weights /= sumWeight;
79  }
80 }
81 
82 
84 (
85  const polyMesh& mesh,
86  const labelList& toGlobal,
87  const Map<label>& toLocal,
88  const vector& position,
89  const vectorField& uVec,
90  const scalarField& dist,
91  scalarField& weights
92 ) const
93 {
94  // Loop over all triangles of all polygons of cell to compute weights
96  DynamicList<scalar> theta(100);
97  DynamicList<point> u(100);
98 
99  const Foam::cell& cFaces = mesh.cells()[cellIndex_];
100 
101  forAll(cFaces, iter)
102  {
103  label facei = cFaces[iter];
104  const face& f = mesh.faces()[facei];
105 
106  // Pout<< "face:" << facei << " at:"
107  // << pointField(mesh.points(), f)
108  // << endl;
109 
110  // Collect the uVec for the face
111  forAll(f, j)
112  {
113  u(j) = uVec[toLocal[f[j]]];
114  }
115 
116  vector v(point::zero);
117  forAll(f, j)
118  {
119  label jPlus1 = f.fcIndex(j);
120  // Pout<< " uj:" << u[j] << " ujPlus1:" << u[jPlus1] << endl;
121 
122  vector temp = u[j] ^ u[jPlus1];
123 
124  scalar magTemp = mag(temp);
125 
126  if (magTemp < vSmall)
127  {
128  continue;
129  }
130 
131  temp /= magTemp;
132 
133  // Pout<< " uj:" << u[j] << " ujPlus1:" << u[jPlus1]
134  // << " temp:" << temp << endl;
135 
136  scalar l = min(mag(u[j] - u[jPlus1]), 2.0);
137  scalar angle = 2.0*Foam::asin(l/2.0);
138 
139  // Pout<< " j:" << j << " l:" << l << " angle:" << angle << endl;
140 
141  v += 0.5*angle*temp;
142  }
143 
144  scalar vNorm = mag(v);
145  v /= vNorm;
146 
147  if ((v & u[0]) < 0)
148  {
149  v = -v;
150  }
151 
152  // Pout<< " v:" << v << endl;
153 
154  // angles between edges
155  forAll(f, j)
156  {
157  label jPlus1 = f.fcIndex(j);
158  // Pout<< " uj:" << u[j] << " ujPlus1:" << u[jPlus1] << endl;
159 
160  vector n0 = u[j]^v;
161  n0 /= mag(n0);
162  vector n1 = u[jPlus1]^v;
163  n1 /= mag(n1);
164 
165  scalar l = min(mag(n0 - n1), 2.0);
166  // Pout<< " l:" << l << endl;
167  alpha(j) = 2.0*Foam::asin(l/2.0);
168 
169  vector temp = n0^n1;
170  if ((temp&v) < 0.0)
171  {
172  alpha[j] = -alpha[j];
173  }
174 
175  l = min(mag(u[j] - v), 2.0);
176  // Pout<< " l:" << l << endl;
177  theta(j) = 2.0*Foam::asin(l/2.0);
178  }
179 
180 
181  bool outlierFlag = false;
182  forAll(f, j)
183  {
184  if (mag(theta[j]) < tol)
185  {
186  outlierFlag = true;
187 
188  label pid = toLocal[f[j]];
189  weights[pid] += vNorm / dist[pid];
190  break;
191  }
192  }
193 
194  if (outlierFlag)
195  {
196  continue;
197  }
198 
199  scalar sum = 0.0;
200  forAll(f, j)
201  {
202  label jMin1 = f.rcIndex(j);
203  sum +=
204  1.0
205  / Foam::tan(theta[j])
206  * (Foam::tan(alpha[j]/2.0) + Foam::tan(alpha[jMin1]/2.0));
207  }
208 
209  // The special case when x lies on the polygon, handle it using 2D mvc.
210  // In the 2D case, alpha = theta
211  if (mag(sum) < tol)
212  {
213  // Calculate weights using face vertices only
214  calcWeights(toLocal, f, u, dist, weights);
215  return;
216  }
217 
218 
219  // Normal 3D case
220  forAll(f, j)
221  {
222  label pid = toLocal[f[j]];
223  label jMin1 = f.rcIndex(j);
224  weights[pid] +=
225  vNorm
226  / sum
227  / dist[pid]
228  / Foam::sin(theta[j])
229  * (Foam::tan(alpha[j]/2.0) + Foam::tan(alpha[jMin1]/2.0));
230  }
231  }
232 
233  // normalise weights
234  scalar sumWeight = sum(weights);
235 
236  if (mag(sumWeight) < tol)
237  {
238  return;
239  }
240  weights /= sumWeight;
241 }
242 
243 
244 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
245 
247 (
248  const polyMesh& mesh,
249  const vector& position,
250  const label cellIndex,
251  const label faceIndex
252 )
253 :
254  cellIndex_((cellIndex != -1) ? cellIndex : mesh.faceOwner()[faceIndex])
255 {
256  // Addressing - face vertices to local points and vice versa
257  const labelList& toGlobal = mesh.cellPoints()[cellIndex_];
258  Map<label> toLocal(2*toGlobal.size());
259  forAll(toGlobal, i)
260  {
261  toLocal.insert(toGlobal[i], i);
262  }
263 
264 
265  // Initialise weights
266  weights_.setSize(toGlobal.size());
267  weights_ = 0.0;
268 
269 
270  // Point-to-vertex vectors and distances
271  vectorField uVec(toGlobal.size());
272  scalarField dist(toGlobal.size());
273 
274  forAll(toGlobal, pid)
275  {
276  const point& pt = mesh.points()[toGlobal[pid]];
277 
278  uVec[pid] = pt-position;
279  dist[pid] = mag(uVec[pid]);
280 
281  // Special case: point is close to vertex
282  if (dist[pid] < tol)
283  {
284  weights_[pid] = 1.0;
285  return;
286  }
287  }
288 
289  // Project onto unit sphere
290  uVec /= dist;
291 
292 
293  if (faceIndex < 0)
294  {
295  // Face data not supplied
297  (
298  mesh,
299  toGlobal,
300  toLocal,
301  position,
302  uVec,
303  dist,
304 
305  weights_
306  );
307  }
308  else
309  {
310  DynamicList<point> u(100);
311  const face& f = mesh.faces()[faceIndex];
312  // Collect the uVec for the face
313  forAll(f, j)
314  {
315  u(j) = uVec[toLocal[f[j]]];
316  }
317 
318  // Calculate weights for face only
319  calcWeights(toLocal, f, u, dist, weights_);
320  }
321 }
322 
323 
324 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:78
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
label rcIndex(const label i) const
Return the reverse circular index, i.e. the previous index.
Definition: UListI.H:65
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
Definition: UListI.H:58
static const Form zero
Definition: VectorSpace.H:118
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:60
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:76
Container to calculate weights for interpolating directly from vertices of cell using Mean Value Coor...
const label cellIndex_
Cell index.
static scalar tol
Tolerance used in calculating barycentric co-ordinates.
scalarField weights_
Weights applied to cell vertices.
const scalarField & weights() const
Interpolation weights (in order of cellPoints)
pointMVCWeight(const polyMesh &mesh, const vector &position, const label celli, const label facei=-1)
Construct from components.
void calcWeights(const Map< label > &toLocal, const face &f, const DynamicList< point > &u, const scalarField &dist, scalarField &weights) const
Calculate weights from single face's vertices only.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:78
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1308
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1295
const labelListList & cellPoints() const
const cellList & cells() const
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
volScalarField alpha(IOobject("alpha", runTime.name(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
List< weight > calcWeights(const polyMesh &mesh, const generatedCellZone &zone, const scalarField &pointXs, const scalarField &cellMinXs, const scalarField &cellMaxXs, const labelList &cellMinOrder, const scalarField &cutXs, const bool interpolate, const bool normalise)
Definition: cellCutPlot.C:848
point position(const polyMesh &mesh, const barycentric &coordinates, const label celli, const label facei, const label faceTrii, const scalar stepFraction)
Return the position given the coordinates and tet topology.
Definition: trackingI.H:224
Namespace for OpenFOAM.
dimensionedScalar asin(const dimensionedScalar &ds)
dimensionedScalar tan(const dimensionedScalar &ds)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
dimensionedScalar sin(const dimensionedScalar &ds)
dimensioned< Type > min(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
pid_t pid()
Return the PID of this process.
Definition: POSIX.C:73
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
defineTypeNameAndDebug(atmosphericBoundaryLayer, 0)
labelList f(nPoints)