Foam::Vandermonde::Vandermonde ( const scalarSquareMatrix& A, const bool checkVandermonde ) : scalarDiagonalMatrix(A.m()), m_(A.m()) { if (checkVandermonde) { for (label i = 0; i < m_; i++) { for (label j = 0; i < m_; j++) { if (A[i][j] != pow(A[1][j], i)) { FatalErrorInFunction << "Source matrix not of Vandermonde type." << nl << abort(FatalError); } } } } for (label i = 0; i < m_; i++) { (*this)[i] = A[1][i]; } }
void Foam::LUsolve ( scalarSquareMatrix& matrix, Field<Type>& sourceSol ) { labelList pivotIndices(matrix.n()); LUDecompose(matrix, pivotIndices); LUBacksubstitute(matrix, pivotIndices, sourceSol); }
Foam::eigenSolver::eigenSolver(const scalarSquareMatrix& A, bool symmetric) : eigenvaluesRe_(A.n()), eigenvaluesIm_(A.n()), eigenvectors_(A.n(), A.n()), H_(), n_(A.n()) { if (symmetric) { eigenvectors_ = A; tridiagonaliseSymmMatrix(); symmTridiagQL(); } else { H_ = A; Hessenberg(); realSchur(); } }
Foam::scalarSquareMatrix Foam::LUinvert( scalarSquareMatrix& luMatrix) { //scalarSquareMatrix luMatrix = *this; scalarSquareMatrix luInvert(luMatrix.n()); scalarField column(luMatrix.n()); labelList pivotIndices(luMatrix.n()); LUDecompose(luMatrix, pivotIndices); for (label j = 0; j < luMatrix.n(); j++) { for (label i = 0; i < luMatrix.n(); i++) { column[i] = 0.0; } column[j] = 1.0; LUBacksubstitute(luMatrix, pivotIndices, column); for (label i = 0; i < luMatrix.n(); i++) { luInvert[i][j] = column[i]; } } return luInvert; }
void Foam::LUBacksubstitute ( const scalarSquareMatrix& luMatrix, const labelList& pivotIndices, Field<Type>& sourceSol ) { label n = luMatrix.n(); label ii = 0; for (register label i=0; i<n; i++) { label ip = pivotIndices[i]; Type sum = sourceSol[ip]; sourceSol[ip] = sourceSol[i]; const scalar* __restrict__ luMatrixi = luMatrix[i]; if (ii != 0) { for (label j=ii-1; j<i; j++) { sum -= luMatrixi[j]*sourceSol[j]; } } else if (sum != pTraits<Type>::zero) { ii = i+1; } sourceSol[i] = sum; } for (register label i=n-1; i>=0; i--) { Type sum = sourceSol[i]; const scalar* __restrict__ luMatrixi = luMatrix[i]; for (register label j=i+1; j<n; j++) { sum -= luMatrixi[j]*sourceSol[j]; } sourceSol[i] = sum/luMatrixi[i]; } }
void multiply ( scalarSquareMatrix& ans, // value changed in return const scalarDiagonalMatrix& A, const scalarSquareMatrix& B, const scalarDiagonalMatrix& C ) { if (A.size() != B.n()) { FatalErrorIn ( "multiply(" "scalarRectangularMatrix& answer)," "const DiagonalMatrix<scalar>& A, " "const scalarRectangularMatrix& B, " "const DiagonalMatrix<scalar>& C" ) << "A and B must have identical inner dimensions but A.m = " << A.size() << " and B.n = " << B.n() << abort(FatalError); } if (B.m() != C.size()) { FatalErrorIn ( "multiply(" "scalarRectangularMatrix& answer)," "const DiagonalMatrix<scalar>& A, " "const scalarRectangularMatrix& B, " "const DiagonalMatrix<scalar>& C" ) << "B and C must have identical inner dimensions but B.m = " << B.m() << " and C.n = " << C.size() << abort(FatalError); } ans = scalarSquareMatrix(B.n(), B.n(), scalar(0)); for (register label i = 0; i < A.size(); i++) { for (register label j = 0; j < C.size(); j++) { ans[i][j] = A[i] * B[i][j] * C[j]; } } }
void Foam::solve ( scalarSquareMatrix& tmpMatrix, Field<Type>& sourceSol ) { label n = tmpMatrix.n(); // Elimination for (register label i=0; i<n; i++) { label iMax = i; scalar largestCoeff = mag(tmpMatrix[iMax][i]); // Swap entries around to find a good pivot for (register label j=i+1; j<n; j++) { if (mag(tmpMatrix[j][i]) > largestCoeff) { iMax = j; largestCoeff = mag(tmpMatrix[iMax][i]); } } if (i != iMax) { //Info<< "Pivoted on " << i << " " << iMax << endl; for (register label k=i; k<n; k++) { Swap(tmpMatrix[i][k], tmpMatrix[iMax][k]); } Swap(sourceSol[i], sourceSol[iMax]); } // Check that the system of equations isn't singular if (mag(tmpMatrix[i][i]) < 1e-20) { FatalErrorIn("solve(scalarSquareMatrix&, Field<Type>& sourceSol)") << "Singular Matrix" << exit(FatalError); } // Reduce to upper triangular form for (register label j=i+1; j<n; j++) { sourceSol[j] -= sourceSol[i]*(tmpMatrix[j][i]/tmpMatrix[i][i]); for (register label k=n-1; k>=i; k--) { tmpMatrix[j][k] -= tmpMatrix[i][k]*tmpMatrix[j][i]/tmpMatrix[i][i]; } } } // Back-substitution for (register label j=n-1; j>=0; j--) { Type ntempvec = pTraits<Type>::zero; for (register label k=j+1; k<n; k++) { ntempvec += tmpMatrix[j][k]*sourceSol[k]; } sourceSol[j] = (sourceSol[j] - ntempvec)/tmpMatrix[j][j]; } }
void Foam::scalarSquareMatrix::LUDecompose ( scalarSquareMatrix& matrix, labelList& pivotIndices ) { label n = matrix.n(); scalar vv[n]; for (register label i=0; i<n; i++) { scalar largestCoeff = 0.0; scalar temp; const scalar* __restrict__ matrixi = matrix[i]; for (register label j=0; j<n; j++) { if ((temp = mag(matrixi[j])) > largestCoeff) { largestCoeff = temp; } } if (largestCoeff == 0.0) { FatalErrorIn ( "scalarSquareMatrix::LUdecompose" "(scalarSquareMatrix& matrix, labelList& rowIndices)" ) << "Singular matrix" << exit(FatalError); } vv[i] = 1.0/largestCoeff; } for (register label j=0; j<n; j++) { scalar* __restrict__ matrixj = matrix[j]; for (register label i=0; i<j; i++) { scalar* __restrict__ matrixi = matrix[i]; scalar sum = matrixi[j]; for (register label k=0; k<i; k++) { sum -= matrixi[k]*matrix[k][j]; } matrixi[j] = sum; } label iMax = 0; scalar largestCoeff = 0.0; for (register label i=j; i<n; i++) { scalar* __restrict__ matrixi = matrix[i]; scalar sum = matrixi[j]; for (register label k=0; k<j; k++) { sum -= matrixi[k]*matrix[k][j]; } matrixi[j] = sum; scalar temp; if ((temp = vv[i]*mag(sum)) >= largestCoeff) { largestCoeff = temp; iMax = i; } } pivotIndices[j] = iMax; if (j != iMax) { scalar* __restrict__ matrixiMax = matrix[iMax]; for (register label k=0; k<n; k++) { Swap(matrixj[k], matrixiMax[k]); } vv[iMax] = vv[j]; } if (matrixj[j] == 0.0) { matrixj[j] = SMALL; } if (j != n-1) { scalar rDiag = 1.0/matrixj[j]; for (register label i=j+1; i<n; i++) { matrix[i][j] *= rDiag; } } } }