FitData.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2016 OpenFOAM Foundation
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
28#include "FitData.H"
29#include "surfaceFields.H"
30#include "volFields.H"
31#include "SVD.H"
32
33// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
34
35template<class Form, class ExtendedStencil, class Polynomial>
37(
38 const fvMesh& mesh,
39 const ExtendedStencil& stencil,
40 const bool linearCorrection,
41 const scalar linearLimitFactor,
42 const scalar centralWeight
43)
44:
46 stencil_(stencil),
47 linearCorrection_(linearCorrection),
48 linearLimitFactor_(linearLimitFactor),
49 centralWeight_(centralWeight),
50 #ifdef SPHERICAL_GEOMETRY
51 dim_(2),
52 #else
53 dim_(mesh.nGeometricD()),
54 #endif
55 minSize_(Polynomial::nTerms(dim_))
56{
57 // Check input
58 if (linearLimitFactor <= SMALL || linearLimitFactor > 3)
59 {
61 << "linearLimitFactor requested = " << linearLimitFactor
62 << " should be between zero and 3"
63 << exit(FatalError);
64 }
65}
66
67
68// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
69
70template<class FitDataType, class ExtendedStencil, class Polynomial>
72(
73 vector& idir, // value changed in return
74 vector& jdir, // value changed in return
75 vector& kdir, // value changed in return
76 const label facei
77)
78{
79 const fvMesh& mesh = this->mesh();
80
81 idir = normalised(mesh.faceAreas()[facei]);
82
83 #ifndef SPHERICAL_GEOMETRY
84 if (mesh.nGeometricD() <= 2) // find the normal direction
85 {
86 if (mesh.geometricD()[0] == -1)
87 {
88 kdir = vector(1, 0, 0);
89 }
90 else if (mesh.geometricD()[1] == -1)
91 {
92 kdir = vector(0, 1, 0);
93 }
94 else
95 {
96 kdir = vector(0, 0, 1);
97 }
98 }
99 else // 3D so find a direction in the plane of the face
100 {
101 const face& f = mesh.faces()[facei];
102 kdir = mesh.points()[f[0]] - mesh.faceCentres()[facei];
103 }
104 #else
105 // Spherical geometry so kdir is the radial direction
106 kdir = mesh.faceCentres()[facei];
107 #endif
108
109 if (mesh.nGeometricD() == 3)
110 {
111 // Remove the idir component from kdir and normalise
112 kdir -= (idir & kdir)*idir;
113
114 scalar magk = mag(kdir);
115
116 if (magk < SMALL)
117 {
119 << exit(FatalError);
120 }
121 else
122 {
123 kdir /= magk;
124 }
125 }
126
127 jdir = kdir ^ idir;
128}
129
130
131template<class FitDataType, class ExtendedStencil, class Polynomial>
133(
134 scalarList& coeffsi,
135 const List<point>& C,
136 const scalar wLin,
137 const label facei
138)
139{
140 vector idir(1,0,0);
141 vector jdir(0,1,0);
142 vector kdir(0,0,1);
143 findFaceDirs(idir, jdir, kdir, facei);
144
145 // Setup the point weights
146 scalarList wts(C.size(), scalar(1));
147 wts[0] = centralWeight_;
148 if (linearCorrection_)
149 {
150 wts[1] = centralWeight_;
151 }
152
153 // Reference point
154 point p0 = this->mesh().faceCentres()[facei];
155
156 // Info<< "Face " << facei << " at " << p0 << " stencil points at:\n"
157 // << C - p0 << endl;
158
159 // p0 -> p vector in the face-local coordinate system
160 vector d;
161
162 // Local coordinate scaling
163 scalar scale = 1;
164
165 // Matrix of the polynomial components
166 scalarRectangularMatrix B(C.size(), minSize_, Zero);
167
168 forAll(C, ip)
169 {
170 const point& p = C[ip];
171
172 d.x() = (p - p0)&idir;
173 d.y() = (p - p0)&jdir;
174 #ifndef SPHERICAL_GEOMETRY
175 d.z() = (p - p0)&kdir;
176 #else
177 d.z() = mag(p) - mag(p0);
178 #endif
179
180 if (ip == 0)
181 {
182 scale = cmptMax(cmptMag((d)));
183 }
184
185 // Scale the radius vector
186 d /= scale;
187
189 (
190 B[ip],
191 d,
192 wts[ip],
193 dim_
194 );
195 }
196
197 // Additional weighting for constant and linear terms
198 for (label i = 0; i < B.m(); i++)
199 {
200 B(i, 0) *= wts[0];
201 B(i, 1) *= wts[0];
202 }
203
204 // Set the fit
205 label stencilSize = C.size();
206 coeffsi.setSize(stencilSize);
207
208 bool goodFit = false;
209 for (int iIt = 0; iIt < 8 && !goodFit; iIt++)
210 {
211 SVD svd(B, SMALL);
212 scalarRectangularMatrix invB(svd.VSinvUt());
213
214 scalar maxCoeff = 0;
215 label maxCoeffi = 0;
216
217 for (label i=0; i<stencilSize; i++)
218 {
219 coeffsi[i] = wts[0]*wts[i]*invB(0, i);
220 if (mag(coeffsi[i]) > maxCoeff)
221 {
222 maxCoeff = mag(coeffsi[i]);
223 maxCoeffi = i;
224 }
225 }
226
227 if (linearCorrection_)
228 {
229 goodFit =
230 (mag(coeffsi[0] - wLin) < linearLimitFactor_*wLin)
231 && (mag(coeffsi[1] - (1 - wLin)) < linearLimitFactor_*(1 - wLin))
232 && maxCoeffi <= 1;
233 }
234 else
235 {
236 // Upwind: weight on face is 1.
237 goodFit =
238 (mag(coeffsi[0] - 1.0) < linearLimitFactor_*1.0)
239 && maxCoeffi <= 1;
240 }
241
242 // if (goodFit && iIt > 0)
243 // {
244 // Info<< "FitData<Polynomial>::calcFit"
245 // << "(const List<point>& C, const label facei" << nl
246 // << "Can now fit face " << facei << " iteration " << iIt
247 // << " with sum of weights " << sum(coeffsi) << nl
248 // << " Weights " << coeffsi << nl
249 // << " Linear weights " << wLin << " " << 1 - wLin << nl
250 // << " sing vals " << svd.S() << endl;
251 // }
252
253 if (!goodFit) // (not good fit so increase weight in the centre and
254 // weight for constant and linear terms)
255 {
256 // if (iIt == 7)
257 // {
258 // WarningInFunction
259 // << "Cannot fit face " << facei << " iteration " << iIt
260 // << " with sum of weights " << sum(coeffsi) << nl
261 // << " Weights " << coeffsi << nl
262 // << " Linear weights " << wLin << " " << 1 - wLin << nl
263 // << " sing vals " << svd.S() << endl;
264 // }
265
266 wts[0] *= 10;
267 if (linearCorrection_)
268 {
269 wts[1] *= 10;
270 }
271
272 for (label j = 0; j < B.n(); j++)
273 {
274 B(0, j) *= 10;
275 B(1, j) *= 10;
276 }
277
278 for (label i = 0; i < B.m(); i++)
279 {
280 B(i, 0) *= 10;
281 B(i, 1) *= 10;
282 }
283 }
284 }
285
286 if (goodFit)
287 {
288 if (linearCorrection_)
289 {
290 // Remove the uncorrected linear coefficients
291 coeffsi[0] -= wLin;
292 coeffsi[1] -= 1 - wLin;
293 }
294 else
295 {
296 // Remove the uncorrected upwind coefficients
297 coeffsi[0] -= 1.0;
298 }
299 }
300 else
301 {
302 // if (debug)
303 // {
305 << "Could not fit face " << facei
306 << " Weights = " << coeffsi
307 << ", reverting to linear." << nl
308 << " Linear weights " << wLin << " " << 1 - wLin << endl;
309 // }
310
311 coeffsi = 0;
312 }
313}
314
315
316template<class FitDataType, class ExtendedStencil, class Polynomial>
318{
319 calcFit();
320 return true;
321}
322
323// ************************************************************************* //
static const Foam::dimensionedScalar B("", Foam::dimless, 18.678)
Graphite solid properties.
Definition: C.H:53
Data for the upwinded and centred polynomial fit interpolation schemes. The linearCorrection_ determi...
Definition: FitData.H:60
bool movePoints()
Recalculate weights (but not stencil) when the mesh moves.
Definition: FitData.C:317
scalar linearLimitFactor() const
Factor the fit is allowed to deviate from the base scheme.
Definition: FitData.H:124
virtual void calcFit()=0
Calculate the fit for all the faces.
void findFaceDirs(vector &idir, vector &jdir, vector &kdir, const label faci)
Find the normal direction (i) and j and k directions for face faci.
Definition: FitData.C:72
void setSize(const label n)
Alias for resize()
Definition: List.H:218
Templated abstract base-class for optional mesh objects used to automate their allocation to the mesh...
Definition: MeshObject.H:91
Polynomial templated on size (order):
Definition: Polynomial.H:78
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
const Cmpt & z() const
Access to the vector z component.
Definition: VectorI.H:85
const Cmpt & y() const
Access to the vector y component.
Definition: VectorI.H:79
const Cmpt & x() const
Access to the vector x component.
Definition: VectorI.H:73
static void addCoeffs(scalar *coeffs, const vector &d, const scalar weight, const direction dim)
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:91
label nGeometricD() const
Return the number of valid geometric dimensions in the mesh.
Definition: polyMesh.C:883
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1108
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1083
const Vector< label > & geometricD() const
Return the vector of geometric directions in mesh.
Definition: polyMesh.C:872
const vectorField & faceCentres() const
const vectorField & faceAreas() const
volScalarField & p
const volScalarField & p0
Definition: EEqn.H:36
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for OpenFOAM.
RectangularMatrix< scalar > scalarRectangularMatrix
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
Definition: quaternionI.H:680
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
void cmptMax(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
error FatalError
void cmptMag(FieldField< Field, Type > &cf, const FieldField< Field, Type > &f)
Vector< scalar > vector
Definition: vector.H:61
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
labelList f(nPoints)
volScalarField & C
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
Foam::surfaceFields.