00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "quadraticFitSnGradData.H"
00027 #include <finiteVolume/surfaceFields.H>
00028 #include <finiteVolume/volFields.H>
00029 #include <OpenFOAM/SVD.H>
00030 #include <OpenFOAM/syncTools.H>
00031
00032
00033
00034 namespace Foam
00035 {
00036 defineTypeNameAndDebug(quadraticFitSnGradData, 0);
00037 }
00038
00039
00040
00041
00042 Foam::quadraticFitSnGradData::quadraticFitSnGradData
00043 (
00044 const fvMesh& mesh,
00045 const scalar cWeight
00046 )
00047 :
00048 MeshObject<fvMesh, quadraticFitSnGradData>(mesh),
00049 centralWeight_(cWeight),
00050 #ifdef SPHERICAL_GEOMETRY
00051 dim_(2),
00052 #else
00053 dim_(mesh.nGeometricD()),
00054 #endif
00055 minSize_
00056 (
00057 dim_ == 1 ? 3 :
00058 dim_ == 2 ? 6 :
00059 dim_ == 3 ? 9 : 0
00060 ),
00061 stencil_(mesh),
00062 fit_(mesh.nInternalFaces())
00063 {
00064 if (debug)
00065 {
00066 Info << "Contructing quadraticFitSnGradData" << endl;
00067 }
00068
00069
00070 if (centralWeight_ < 1 - SMALL)
00071 {
00072 FatalErrorIn("quadraticFitSnGradData::quadraticFitSnGradData")
00073 << "centralWeight requested = " << centralWeight_
00074 << " should not be less than one"
00075 << exit(FatalError);
00076 }
00077
00078 if (minSize_ == 0)
00079 {
00080 FatalErrorIn("quadraticFitSnGradData")
00081 << " dimension must be 1,2 or 3, not" << dim_ << exit(FatalError);
00082 }
00083
00084
00085 surfaceScalarField snGradPolySize
00086 (
00087 IOobject
00088 (
00089 "quadraticFitSnGradPolySize",
00090 "constant",
00091 mesh,
00092 IOobject::NO_READ,
00093 IOobject::NO_WRITE
00094 ),
00095 mesh,
00096 dimensionedScalar("quadraticFitSnGradPolySize", dimless, scalar(0))
00097 );
00098
00099
00100
00101 List<List<point> > stencilPoints(stencil_.stencil().size());
00102 stencil_.collectData
00103 (
00104 mesh.C(),
00105 stencilPoints
00106 );
00107
00108
00109
00110 for(label faci = 0; faci < mesh.nInternalFaces(); faci++)
00111 {
00112 snGradPolySize[faci] = calcFit(stencilPoints[faci], faci);
00113 }
00114
00115 if (debug)
00116 {
00117 snGradPolySize.write();
00118 Info<< "quadraticFitSnGradData::quadraticFitSnGradData() :"
00119 << "Finished constructing polynomialFit data"
00120 << endl;
00121 }
00122 }
00123
00124
00125
00126
00127 void Foam::quadraticFitSnGradData::findFaceDirs
00128 (
00129 vector& idir,
00130 vector& jdir,
00131 vector& kdir,
00132 const fvMesh& mesh,
00133 const label faci
00134 )
00135 {
00136 idir = mesh.Sf()[faci];
00137 idir /= mag(idir);
00138
00139 #ifndef SPHERICAL_GEOMETRY
00140 if (mesh.nGeometricD() <= 2)
00141 {
00142 if (mesh.geometricD()[0] == -1)
00143 {
00144 kdir = vector(1, 0, 0);
00145 }
00146 else if (mesh.geometricD()[1] == -1)
00147 {
00148 kdir = vector(0, 1, 0);
00149 }
00150 else
00151 {
00152 kdir = vector(0, 0, 1);
00153 }
00154 }
00155 else
00156 {
00157 const face& f = mesh.faces()[faci];
00158 kdir = mesh.points()[f[0]] - mesh.points()[f[1]];
00159 }
00160 #else
00161
00162 kdir = mesh.Cf()[faci];
00163 #endif
00164
00165 if (mesh.nGeometricD() == 3)
00166 {
00167
00168 kdir -= (idir & kdir)*idir;
00169
00170 scalar magk = mag(kdir);
00171
00172 if (magk < SMALL)
00173 {
00174 FatalErrorIn("findFaceDirs") << " calculated kdir = zero"
00175 << exit(FatalError);
00176 }
00177 else
00178 {
00179 kdir /= magk;
00180 }
00181 }
00182
00183 jdir = kdir ^ idir;
00184 }
00185
00186
00187 Foam::label Foam::quadraticFitSnGradData::calcFit
00188 (
00189 const List<point>& C,
00190 const label faci
00191 )
00192 {
00193 vector idir(1,0,0);
00194 vector jdir(0,1,0);
00195 vector kdir(0,0,1);
00196 findFaceDirs(idir, jdir, kdir, mesh(), faci);
00197
00198 scalarList wts(C.size(), scalar(1));
00199 wts[0] = centralWeight_;
00200 wts[1] = centralWeight_;
00201
00202 point p0 = mesh().faceCentres()[faci];
00203 scalar scale = 0;
00204
00205
00206 scalarRectangularMatrix B(C.size(), minSize_, scalar(0));
00207
00208 for(label ip = 0; ip < C.size(); ip++)
00209 {
00210 const point& p = C[ip];
00211
00212 scalar px = (p - p0)&idir;
00213 scalar py = (p - p0)&jdir;
00214 #ifdef SPHERICAL_GEOMETRY
00215 scalar pz = mag(p) - mag(p0);
00216 #else
00217 scalar pz = (p - p0)&kdir;
00218 #endif
00219
00220 if (ip == 0) scale = max(max(mag(px), mag(py)), mag(pz));
00221
00222 px /= scale;
00223 py /= scale;
00224 pz /= scale;
00225
00226 label is = 0;
00227
00228 B[ip][is++] = wts[0]*wts[ip];
00229 B[ip][is++] = wts[0]*wts[ip]*px;
00230 B[ip][is++] = wts[ip]*sqr(px);
00231
00232 if (dim_ >= 2)
00233 {
00234 B[ip][is++] = wts[ip]*py;
00235 B[ip][is++] = wts[ip]*px*py;
00236 B[ip][is++] = wts[ip]*sqr(py);
00237 }
00238 if (dim_ == 3)
00239 {
00240 B[ip][is++] = wts[ip]*pz;
00241 B[ip][is++] = wts[ip]*px*pz;
00242
00243 B[ip][is++] = wts[ip]*sqr(pz);
00244 }
00245 }
00246
00247
00248 label stencilSize = C.size();
00249 fit_[faci].setSize(stencilSize);
00250 scalarList singVals(minSize_);
00251 label nSVDzeros = 0;
00252
00253 const scalar& deltaCoeff = mesh().deltaCoeffs()[faci];
00254
00255 bool goodFit = false;
00256 for(int iIt = 0; iIt < 10 && !goodFit; iIt++)
00257 {
00258 SVD svd(B, SMALL);
00259
00260 scalar fit0 = wts[0]*wts[0]*svd.VSinvUt()[1][0]/scale;
00261 scalar fit1 = wts[0]*wts[1]*svd.VSinvUt()[1][1]/scale;
00262
00263 goodFit =
00264 fit0 < 0 && fit1 > 0
00265 && mag(fit0 + deltaCoeff) < 0.5*deltaCoeff
00266 && mag(fit1 - deltaCoeff) < 0.5*deltaCoeff;
00267
00268 if (goodFit)
00269 {
00270 fit_[faci][0] = fit0;
00271 fit_[faci][1] = fit1;
00272 for(label i = 2; i < stencilSize; i++)
00273 {
00274 fit_[faci][i] = wts[0]*wts[i]*svd.VSinvUt()[1][i]/scale;
00275 }
00276 singVals = svd.S();
00277 nSVDzeros = svd.nZeros();
00278 }
00279 else
00280 {
00281 wts[0] *= 10;
00282 wts[1] *= 10;
00283
00284 for(label i = 0; i < B.n(); i++)
00285 {
00286 B[i][0] *= 10;
00287 B[i][1] *= 10;
00288 }
00289
00290 for(label j = 0; j < B.m(); j++)
00291 {
00292 B[0][j] *= 10;
00293 B[1][j] *= 10;
00294 }
00295 }
00296 }
00297
00298 if (goodFit)
00299 {
00300
00301 fit_[faci][0] += deltaCoeff;
00302 fit_[faci][1] -= deltaCoeff;
00303 }
00304 else
00305 {
00306 Pout<< "quadratifFitSnGradData could not fit face " << faci
00307 << " fit_[faci][0] = " << fit_[faci][0]
00308 << " fit_[faci][1] = " << fit_[faci][1]
00309 << " deltaCoeff = " << deltaCoeff << endl;
00310 fit_[faci] = 0;
00311 }
00312
00313 return minSize_ - nSVDzeros;
00314 }
00315
00316 bool Foam::quadraticFitSnGradData::movePoints()
00317 {
00318 notImplemented("quadraticFitSnGradData::movePoints()");
00319
00320 return true;
00321 }
00322
00323
00324