bool momentSetIsValid(const scalarList& momentList) { label L = 0.5*(momentList.size() - 2); labelList pivotIndices(L + 1); scalarSquareMatrix hankelHadamardMatrix(L + 1, L + 1, 0.0); for (label m = 0; m < 2; ++m) { for (label row = 0; row < L + 1; ++row) { for (label col = 0; col < L + 1; ++col) { hankelHadamardMatrix[row][col] = momentList[row + col + m]; } } LUDecompose(hankelHadamardMatrix, pivotIndices); // This checks whether the number of row evaluations is // odd or even. See numerical recipes. label d = 1; for (label size = 0; size < L + 1; ++size) { if (size != pivotIndices[size]) { d *= -1.0; } } scalar sumDiagonal = d; for (label diag = 0; diag < L + 1; ++diag) { sumDiagonal *= hankelHadamardMatrix[diag][diag]; } if (sumDiagonal < 0) { return false; } } return true; }
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; } }
void Foam::CentredFitSnGradData<Polynomial>::calcFit ( scalarList& coeffsi, const List<point>& C, const scalar wLin, const scalar deltaCoeff, const label facei ) { vector idir(1,0,0); vector jdir(0,1,0); vector kdir(0,0,1); this->findFaceDirs(idir, jdir, kdir, facei); // Setup the point weights scalarList wts(C.size(), scalar(1)); wts[0] = this->centralWeight(); wts[1] = this->centralWeight(); // Reference point point p0 = this->mesh().faceCentres()[facei]; // 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(), this->minSize(), scalar(0)); forAll(C, ip) { const point& p = C[ip]; const vector p0p = p - p0; d.x() = p0p & idir; d.y() = p0p & jdir; d.z() = p0p & kdir; if (ip == 0) { scale = cmptMax(cmptMag((d))); } // Scale the radius vector d /= scale; Polynomial::addCoeffs(B[ip], d, wts[ip], this->dim()); } // Additional weighting for constant and linear terms for (label i = 0; i < B.m(); 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); scalarRectangularMatrix invB(svd.VSinvUt()); for (label i=0; i<stencilSize; i++) { coeffsi[i] = wts[1]*wts[i]*invB(1, i)/scale; } goodFit = ( mag(wts[0]*wts[0]*invB(0, 0) - wLin) < this->linearLimitFactor()*wLin) && (mag(wts[0]*wts[1]*invB(0, 1) - (1 - wLin) ) < this->linearLimitFactor()*(1 - wLin)) && coeffsi[0] < 0 && coeffsi[1] > 0 && mag(coeffsi[0] + deltaCoeff) < 0.5*deltaCoeff && mag(coeffsi[1] - deltaCoeff) < 0.5*deltaCoeff; if (!goodFit) { // (not good fit so increase weight in the centre and weight // for constant and linear terms) WarningInFunction << "Cannot fit face " << facei << " iteration " << iIt << " with sum of weights " << sum(coeffsi) << nl << " Weights " << coeffsi << nl << " Linear weights " << wLin << " " << 1 - wLin << nl << " deltaCoeff " << deltaCoeff << nl << " sing vals " << svd.S() << nl << "Components of goodFit:\n" << " wts[0]*wts[0]*invB(0, 0) = " << wts[0]*wts[0]*invB(0, 0) << nl << " wts[0]*wts[1]*invB(0, 1) = " << wts[0]*wts[1]*invB(0, 1) << " dim = " << this->dim() << endl; wts[0] *= 10; wts[1] *= 10; for (label j = 0; j < B.n(); j++) { B(0, j) *= 10; B(1, j) *= 10; } for (label i = 0; i < B.m(); i++) { B(i, 0) *= 10; B(i, 1) *= 10; } } } if (goodFit) { // Remove the uncorrected coefficients coeffsi[0] += deltaCoeff; coeffsi[1] -= deltaCoeff; } else { WarningInFunction << "Could not fit face " << facei << " Coefficients = " << coeffsi << ", reverting to uncorrected." << endl; coeffsi = 0; } }