void LU::solve(int const nx, double* X, double const* B) const { if (!isNonsingular()) { throw std::runtime_error("Matrix is singular."); } // Pivot B into X. for (int i = 0; i < m_rows; ++i) { for (int j = 0; j < nx; ++j) { X[i * nx + j] = B[m_piv[i] * nx + j]; } } // Solve L*Y = B(piv,:) for (int k = 0; k < m_cols; ++k) { for (int i = k + 1; i < m_cols; ++i) { for (int j = 0; j < nx; ++j) { X[i * nx + j] -= X[k * nx + j] * m_LU[i * m_cols + k]; } } } // Solve U*X = Y; for (int k = m_cols - 1; k >= 0; --k) { for (int j = 0; j < nx; ++j) { X[k * nx + j] /= m_LU[k * m_cols + k]; } for (int i = 0; i < k; ++i) { for (int j = 0; j < nx; j++) { X[i * nx + j] -= X[k * nx + j] * m_LU[i * m_cols + k]; } } } }
LUDecomposition::Matrix LUDecomposition::solve (const Matrix& B) const { BOOST_UBLAS_CHECK((int)B.size1() == m, bad_size("Matrix row dimensions must agree.")); BOOST_UBLAS_CHECK(isNonsingular(), singular("Matrix is singular.")); // Copy right hand side with pivoting int nx = B.size2(); Matrix X(m,nx); for (int i = 0; i < m; i++) { row(X,i) = row(B, piv(i)); } // Solve L*Y = B(piv,:) for (int k = 0; k < n; k++) { for (int i = k+1; i < n; i++) { for (int j = 0; j < nx; j++) { X(i,j) -= X(k,j)*LU(i,k); } } } // Solve U*X = Y; for (int k = n-1; k >= 0; k--) { for (int j = 0; j < nx; j++) { X(k,j) /= LU(k,k); } for (int i = 0; i < k; i++) { for (int j = 0; j < nx; j++) { X(i,j) -= X(k,j)*LU(i,k); } } } return X; }
void solveLU3x3(sLU& A, float x[3], float b[3]) { //TNT::Array1D<float> jamaB = TNT::Array1D<float>(3, &b[0]); //TNT::Array1D<float> jamaX = A.solve(jamaB); // Solve A, B { if (!isNonsingular(A)) { x[0]=0.0f; x[1]=0.0f; x[2]=0.0f; return; } //Array1D<Real> Ax = permute_copy(b, piv); float Ax[3]; // permute copy: b , A.piv { for (int i = 0; i < 3; i++) Ax[i] = b[A.piv[i]]; } // Solve L*Y = B(piv) for (int k = 0; k < 3; k++) { for (int i = k+1; i < 3; i++) { Ax[i] -= Ax[k]*A.values[i][k]; } } // Solve U*X = Y; for (int k = 2; k >= 0; k--) { Ax[k] /= A.values[k][k]; for (int i = 0; i < k; i++) Ax[i] -= Ax[k]*A.values[i][k]; } x[0] = Ax[0]; x[1] = Ax[1]; x[2] = Ax[2]; return; } }
////////////////////////////////////////////////////////////////////// // Compute the eigenvalues of the advected texture ////////////////////////////////////////////////////////////////////// void WTURBULENCE::computeEigenvalues(float *_eigMin, float *_eigMax) { // stats float maxeig = -1.; float mineig = 10.; // texture coordinate eigenvalues for (int z = 1; z < _zResSm-1; z++) { for (int y = 1; y < _yResSm-1; y++) for (int x = 1; x < _xResSm-1; x++) { const int index = x+ y *_resSm[0] + z*_slabSizeSm; // compute jacobian float jacobian[3][3] = { { minDx(x, y, z, _tcU, _resSm), minDx(x, y, z, _tcV, _resSm), minDx(x, y, z, _tcW, _resSm) } , { minDy(x, y, z, _tcU, _resSm), minDy(x, y, z, _tcV, _resSm), minDy(x, y, z, _tcW, _resSm) } , { minDz(x, y, z, _tcU, _resSm), minDz(x, y, z, _tcV, _resSm), minDz(x, y, z, _tcW, _resSm) } }; // ONLY compute the eigenvalues after checking that the matrix // is nonsingular sLU LU = computeLU(jacobian); if (isNonsingular(LU)) { // get the analytic eigenvalues, quite slow right now... Vec3 eigenvalues = Vec3(1.); computeEigenvalues3x3( &eigenvalues[0], jacobian); _eigMax[index] = MAX3V(eigenvalues); _eigMin[index] = MIN3V(eigenvalues); maxeig = MAX(_eigMax[index],maxeig); mineig = MIN(_eigMin[index],mineig); } else { _eigMax[index] = 10.0f; _eigMin[index] = 0.1; } } } }