void Foam::FitData<FitDataType, ExtendedStencil, Polynomial>::calcFit ( scalarList& coeffsi, const List<point>& C, const scalar wLin, const label facei ) { vector idir(1,0,0); vector jdir(0,1,0); vector kdir(0,0,1); findFaceDirs(idir, jdir, kdir, facei); // Setup the point weights scalarList wts(C.size(), scalar(1)); wts[0] = centralWeight_; if (linearCorrection_) { wts[1] = centralWeight_; } // Reference point point p0 = this->mesh().faceCentres()[facei]; // Info << "Face " << facei << " at " << p0 << " stencil points at:\n" // << C - p0 << endl; // p0 -> p vector in the face-local coordinate system vector d; // Local coordinate scaling scalar scale = 1; // Matrix of the polynomial components scalarRectangularMatrix B(C.size(), minSize_, scalar(0)); for(label ip = 0; ip < C.size(); ip++) { const point& p = C[ip]; d.x() = (p - p0)&idir; d.y() = (p - p0)&jdir; # ifndef SPHERICAL_GEOMETRY d.z() = (p - p0)&kdir; # else d.z() = mag(p) - mag(p0); # endif if (ip == 0) { scale = cmptMax(cmptMag((d))); } // Scale the radius vector d /= scale; Polynomial::addCoeffs ( B[ip], d, wts[ip], dim_ ); } // Additional weighting for constant and linear terms for(label i = 0; i < B.n(); i++) { B[i][0] *= wts[0]; B[i][1] *= wts[0]; } // Set the fit label stencilSize = C.size(); coeffsi.setSize(stencilSize); bool goodFit = false; for(int iIt = 0; iIt < 8 && !goodFit; iIt++) { SVD svd(B, SMALL); scalar maxCoeff = 0; label maxCoeffi = 0; for(label i=0; i<stencilSize; i++) { coeffsi[i] = wts[0]*wts[i]*svd.VSinvUt()[0][i]; if (mag(coeffsi[i]) > maxCoeff) { maxCoeff = mag(coeffsi[i]); maxCoeffi = i; } } if (linearCorrection_) { goodFit = (mag(coeffsi[0] - wLin) < linearLimitFactor_*wLin) && (mag(coeffsi[1] - (1 - wLin)) < linearLimitFactor_*(1 - wLin)) && maxCoeffi <= 1; } else { // Upwind: weight on face is 1. goodFit = (mag(coeffsi[0] - 1.0) < linearLimitFactor_*1.0) && maxCoeffi <= 1; } // if (goodFit && iIt > 0) // { // Info << "FitData<Polynomial>::calcFit" // << "(const List<point>& C, const label facei" << nl // << "Can now fit face " << facei << " iteration " << iIt // << " with sum of weights " << sum(coeffsi) << nl // << " Weights " << coeffsi << nl // << " Linear weights " << wLin << " " << 1 - wLin << nl // << " sing vals " << svd.S() << endl; // } if (!goodFit) // (not good fit so increase weight in the centre and weight // for constant and linear terms) { // if (iIt == 7) // { // WarningIn // ( // "FitData<Polynomial>::calcFit" // "(const List<point>& C, const label facei" // ) << "Cannot fit face " << facei << " iteration " << iIt // << " with sum of weights " << sum(coeffsi) << nl // << " Weights " << coeffsi << nl // << " Linear weights " << wLin << " " << 1 - wLin << nl // << " sing vals " << svd.S() << endl; // } wts[0] *= 10; if (linearCorrection_) { wts[1] *= 10; } for(label j = 0; j < B.m(); j++) { B[0][j] *= 10; B[1][j] *= 10; } for(label i = 0; i < B.n(); i++) { B[i][0] *= 10; B[i][1] *= 10; } } } if (goodFit) { if (linearCorrection_) { // Remove the uncorrected linear coefficients coeffsi[0] -= wLin; coeffsi[1] -= 1 - wLin; } else { // Remove the uncorrected upwind coefficients coeffsi[0] -= 1.0; } } else { // if (debug) // { WarningIn ( "FitData<Polynomial>::calcFit(..)" ) << "Could not fit face " << facei << " Weights = " << coeffsi << ", reverting to linear." << nl << " Linear weights " << wLin << " " << 1 - wLin << endl; // } coeffsi = 0; } }
Foam::label Foam::quadraticFitSnGradData::calcFit ( const List<point>& C, const label faci ) { vector idir(1,0,0); vector jdir(0,1,0); vector kdir(0,0,1); findFaceDirs(idir, jdir, kdir, mesh(), faci); scalarList wts(C.size(), scalar(1)); wts[0] = centralWeight_; wts[1] = centralWeight_; point p0 = mesh().faceCentres()[faci]; scalar scale = 0; // calculate the matrix of the polynomial components scalarRectangularMatrix B(C.size(), minSize_, scalar(0)); for(label ip = 0; ip < C.size(); ip++) { const point& p = C[ip]; scalar px = (p - p0)&idir; scalar py = (p - p0)&jdir; #ifdef SPHERICAL_GEOMETRY scalar pz = mag(p) - mag(p0); #else scalar pz = (p - p0)&kdir; #endif if (ip == 0) scale = max(max(mag(px), mag(py)), mag(pz)); px /= scale; py /= scale; pz /= scale; label is = 0; B[ip][is++] = wts[0]*wts[ip]; B[ip][is++] = wts[0]*wts[ip]*px; B[ip][is++] = wts[ip]*sqr(px); if (dim_ >= 2) { B[ip][is++] = wts[ip]*py; B[ip][is++] = wts[ip]*px*py; B[ip][is++] = wts[ip]*sqr(py); } if (dim_ == 3) { B[ip][is++] = wts[ip]*pz; B[ip][is++] = wts[ip]*px*pz; //B[ip][is++] = wts[ip]*py*pz; B[ip][is++] = wts[ip]*sqr(pz); } } // Set the fit label stencilSize = C.size(); fit_[faci].setSize(stencilSize); scalarList singVals(minSize_); label nSVDzeros = 0; const scalar& deltaCoeff = mesh().deltaCoeffs()[faci]; bool goodFit = false; for(int iIt = 0; iIt < 10 && !goodFit; iIt++) { SVD svd(B, SMALL); scalar fit0 = wts[0]*wts[0]*svd.VSinvUt()[1][0]/scale; scalar fit1 = wts[0]*wts[1]*svd.VSinvUt()[1][1]/scale; goodFit = fit0 < 0 && fit1 > 0 && mag(fit0 + deltaCoeff) < 0.5*deltaCoeff && mag(fit1 - deltaCoeff) < 0.5*deltaCoeff; if (goodFit) { fit_[faci][0] = fit0; fit_[faci][1] = fit1; for(label i = 2; i < stencilSize; i++) { fit_[faci][i] = wts[0]*wts[i]*svd.VSinvUt()[1][i]/scale; } singVals = svd.S(); nSVDzeros = svd.nZeros(); } else // (not good fit so increase weight in the centre and for linear) { wts[0] *= 10; wts[1] *= 10; for(label i = 0; i < B.n(); i++) { B[i][0] *= 10; B[i][1] *= 10; } for(label j = 0; j < B.m(); j++) { B[0][j] *= 10; B[1][j] *= 10; } } } if (goodFit) { // remove the uncorrected snGradScheme coefficients fit_[faci][0] += deltaCoeff; fit_[faci][1] -= deltaCoeff; } else { Pout<< "quadratifFitSnGradData could not fit face " << faci << " fit_[faci][0] = " << fit_[faci][0] << " fit_[faci][1] = " << fit_[faci][1] << " deltaCoeff = " << deltaCoeff << endl; fit_[faci] = 0; } return minSize_ - nSVDzeros; }